You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
    }
}

问题根源与改进方案

核心问题

  1. Update轮询帧不准确:VideoPlayer的frame可能因帧率波动跳过目标值(比如视频帧率高于游戏帧率时),导致错过暂停时机;同时else if逻辑会让按键判断和帧判断互斥,按键事件可能被帧判断覆盖,导致无响应。
  2. 无状态控制:没有跟踪当前要跳转的目标帧,也没有限制播放中重复按键,导致重复触发。
  3. 未处理视频准备状态:视频未加载完成时操作可能导致异常,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:02:46