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

Unity WebGL下VideoPlayer更新Slider进度导致视频播放阻塞

Unity WebGL VideoPlayer更新进度条导致视频仅显示首帧故障修复

问题表现

  • 运行平台:Unity WebGL
  • 故障现象:点击播放按钮后视频仅渲染第一帧就停止,注释掉Update生命周期中给进度Slider赋值的代码行后,视频可正常播放
  • 定位到的问题代码段:
if (video.isPlaying)
{
    if (!video.isPrepared) return;
    videoSlider.value = (float)NTime; // 触发故障的代码行
}
  • 关联的进度计算逻辑:
// NTime依赖Duration计算
public ulong Duration
{
    get { return (ulong)(video.frameCount / video.frameRate); }
}
public double NTime
{
    get { return VideoTime / Duration; }
}

故障根因

两个问题叠加导致故障,在WebGL平台下100%触发:

  1. Slider事件循环触发Seek:进度条Slider的onValueChanged事件已绑定SeekSlider跳转方法,代码主动修改videoSlider.value时会直接触发该事件,每帧执行一次视频进度跳转,把视频进度拉回计算值,导致播放头无法正常前进。
  2. 除零错误生成无效值:WebGL平台视频解码依赖浏览器原生能力,isPrepared返回true的初始几帧内,video.frameCount尚未拿到有效解码数据,返回值为0,直接导致Duration计算结果为0,NTime做除法时得到NaN/无穷大的无效值,触发Slider异常的同时,Seek方法会把视频进度重置到0点,最终只渲染第一帧。

修复方案

按以下步骤修改代码即可:

  1. 先在SliderVideo类中添加状态锁字段,避免代码更新Slider时误触发进度跳转:
// 加在类的字段定义区域
private bool isUpdatingSlider = false;
  1. 修改SeekSlider方法,开头增加锁判断:
public void SeekSlider()
{
    // 代码主动更新Slider时不触发跳转
    if (isUpdatingSlider) return;
    video.time = (videoSlider.value * Duration); 
}
  1. 修复Duration属性的有效性校验,避免除零:
public ulong Duration
{
    get 
    {
        // 元数据无效时返回兜底值,避免除零
        if (!video.isPrepared || video.frameCount <= 0 || video.frameRate <= 0)
            return 1;
        return (ulong)(video.frameCount / video.frameRate); 
    }
}
  1. 优化NTime属性,钳制取值范围在Slider合法区间内:
public double NTime
{
    get 
    {
        double duration = Duration;
        if (duration <= 0) return 0;
        double nTime = VideoTime / duration;
        // 进度值固定在0-1区间,避免超出Slider默认取值范围
        return System.Math.Clamp(nTime, 0d, 1d);
    }
}
  1. 修改Update中Slider赋值逻辑,加锁保护:
private void Update()
{
    if (video.isPlaying)
    {
        if (!video.isPrepared) return;
        // 赋值前加锁
        isUpdatingSlider = true;
        videoSlider.value = (float)NTime;
        // 赋值完成解锁
        isUpdatingSlider = false;

        video.SetDirectAudioVolume(0, volumeSlider.value);
    }

    // 以下全屏逻辑保持原有代码不变
    if (fullScreen)
    {
        if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
        {
            timerMouse = 0;
            buttons.gameObject.SetActive(true);

        }
        else
        {
            timerMouse += Time.deltaTime;

            if (timerMouse > 3)
            {
                timerMouse = 3;
                buttons.gameObject.SetActive(false);
            }
        }
    }
}

注:该问题仅在WebGL平台高频触发是因为WebGL下VideoPlayer的元数据加载时序和Editor/Standalone平台存在差异,Editor等平台isPrepared返回true时frameCount已拿到有效值,不会触发除零,但Slider事件循环触发Seek的隐患在所有平台都存在。

内容的提问来源于stack exchange,提问作者Raoul L'artiste

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:36:19