Unity VideoPlayer按空格分段播放卡顿问题及优化求助
解决Unity VideoPlayer分段跳转卡顿问题
在Unity中,我用一段角色分段向前跳跃的视频做交互,写了一段C#脚本通过大量IF/ELSE语句实现按空格键跳转到指定帧并暂停的功能,但运行场景时卡顿严重:半数按键无响应,偶尔还会触发两次跳转。
我的逻辑是:启动场景时暂停视频,按下空格键后播放至第24帧暂停,再次按下则播放至第48帧暂停,以此类推。这个方法能运行但极不可靠,有时要多次按空格才生效,有时角色刚跳一半就跳到下一帧。
我注意到VideoPlayer的isPrepared属性可能能解决问题,但不知道正确的实现方式,求改进建议。
原实现代码
// 启动时暂停视频 void Start() { _MiniGame.Pause(); } // 按空格键触发跳跃 void Update() { if (Input.GetKeyUp(KeyCode.Space)) { Debug.Log("Spacebar pressed"); _MiniGame.Play(); } else if (_MiniGame.frame == 24) { _MiniGame.Pause(); } else if (_MiniGame.frame == 48) { _MiniGame.Pause(); } else if (_MiniGame.frame == 72) { _MiniGame.Pause(); } else if (_MiniGame.frame == 96) { _MiniGame.Pause(); } else if (_MiniGame.frame == 120) { _MiniGame.Pause(); } else if (_MiniGame.frame == 144) { _MiniGame.Pause(); } }
问题根源与改进方案
核心问题
- Update轮询帧不准确:VideoPlayer的
frame可能因帧率波动跳过目标值(比如视频帧率高于游戏帧率时),导致错过暂停时机;同时else if逻辑会让按键判断和帧判断互斥,按键事件可能被帧判断覆盖,导致无响应。 - 无状态控制:没有跟踪当前要跳转的目标帧,也没有限制播放中重复按键,导致重复触发。
- 未处理视频准备状态:视频未加载完成时操作可能导致异常,
isPrepared就是用来确保视频就绪的关键属性。
改进后的实现
using UnityEngine; using UnityEngine.Video; public class VideoJumpController : MonoBehaviour { [SerializeField] private VideoPlayer _MiniGame; // 分段目标帧列表,可在Inspector里直接编辑 [SerializeField] private int[] targetFrames = {24, 48, 72, 96, 120, 144}; private int currentTargetIndex = 0; private bool isPlayingToTarget = false; void Awake() { // 监听帧变化事件,精准捕获目标帧 _MiniGame.frameChanged += OnVideoFrameChanged; // 监听视频准备完成事件 _MiniGame.prepareCompleted += OnVideoPrepared; } void Start() { // 先让视频进入准备状态 _MiniGame.Prepare(); } void Update() { // 只有视频准备完成且未在播放到目标帧的过程中,才响应按键 if (Input.GetKeyUp(KeyCode.Space) && _MiniGame.isPrepared && !isPlayingToTarget) { Debug.Log("Spacebar pressed"); // 如果已经到最后一个目标帧,可重置索引(根据需求调整) if (currentTargetIndex >= targetFrames.Length) { currentTargetIndex = 0; _MiniGame.frame = 0; } isPlayingToTarget = true; _MiniGame.Play(); } } private void OnVideoFrameChanged(VideoPlayer source) { // 检查当前帧是否达到目标帧 if (isPlayingToTarget && source.frame == targetFrames[currentTargetIndex]) { source.Pause(); isPlayingToTarget = false; currentTargetIndex++; } } private void OnVideoPrepared(VideoPlayer source) { // 视频准备完成后初始暂停 source.Pause(); } void OnDestroy() { // 移除监听,避免内存泄漏 _MiniGame.frameChanged -= OnVideoFrameChanged; _MiniGame.prepareCompleted -= OnVideoPrepared; } }
关键优化点
- 用列表管理目标帧:替换大量IF/ELSE,可直接在Inspector修改分段点,更灵活。
- 帧事件监听:通过
frameChanged事件精准捕获目标帧,避免Update轮询的丢失问题。 - 状态锁控制:用
isPlayingToTarget变量防止播放过程中重复按键,避免多次触发。 - 利用isPrepared:通过
prepareCompleted事件确保视频就绪后再操作,避免未加载完成时的异常。
内容的提问来源于stack exchange,提问作者Svidt
相关产品推荐
相关产品推荐

