⭐ Unity AVProVideo插件自带播放器 脚本重构 实现视频激活重置功能

发布于:2025-05-31 ⋅ 阅读:(24) ⋅ 点赞:(0)

一、功能概述

本笔记记录直接修改插件自带的场景播放其中 原始的 MediaPlayerUI 脚本,实现激活时自动重置播放器的功能。 我用的插件版本是 AVPro Video - Ultra Edition 2.7.3

修改后的脚本将具备以下特性:

  • 激活 GameObject 时自动重置播放位置到开头

  • 可配置是否在重置后自动开始播放

  • 可配置重置前的延迟时间

  • 视频播放结束后自动回到开头

  • 保留原始脚本所有功能

二、修改步骤

1. 添加新变量

在类变量声明区域添加以下变量:

[Header("Activation Behavior")]
[Tooltip("Reset playback to beginning when enabled")]
[SerializeField] bool _resetOnEnable = true;

[Tooltip("Automatically start playback after reset")]
[SerializeField] bool _playOnReset = true;

[Tooltip("Delay before resetting after enable (seconds)")]
[SerializeField] float _resetDelay = 0.1f;

private Coroutine _resetCoroutine;

2. 添加 ResetPlayer 方法

在 Start() 方法后添加:

/// <summary>
/// Resets the player to beginning and optionally starts playback
/// </summary>
public void ResetPlayer()
{
    if (_mediaPlayer == null || _mediaPlayer.Control == null)
    {
        Debug.LogWarning("MediaPlayer or Control is not available", this);
        return;
    }

    // Reset playback position
    _mediaPlayer.Control.Seek(0);
    
    // Reset audio state
    _audioVolume = 1f;
    _audioFade = 1f;
    _isAudioFadingUpToPlay = true;
    _audioFadeTime = 0f;
    ApplyAudioVolume();
    
    // Update UI
    UpdateVolumeSlider();
    
    // Start playback if configured to do so
    if (_playOnReset)
    {
        _mediaPlayer.Play();
        
        // Trigger play feedback if overlay manager exists
        if (_overlayManager)
        {
            _overlayManager.TriggerFeedback(OverlayManager.Feedback.Play);
        }
    }
    else
    {
        _mediaPlayer.Pause();
    }
    
    // Ensure controls are visible
    _controlsFade = 1f;
    if (_controlsGroup != null)
    {
        _controlsGroup.alpha = 1f;
        _controlsGroup.gameObject.SetActive(true);
    }
    
    // Update timeline slider
    if (_sliderTime != null)
    {
        _sliderTime.value = 0f;
    }
}

3. 修改/添加 OnEnable 方法

private void OnEnable()
{
    if (_resetOnEnable)
    {
        // Start reset coroutine with small delay to ensure everything is initialized
        if (_resetCoroutine != null)
        {
            StopCoroutine(_resetCoroutine);
        }
        _resetCoroutine = StartCoroutine(DelayedReset());
    }
}

4. 添加 OnDisable 方法

private void OnDisable()
{
    if (_resetCoroutine != null)
    {
        StopCoroutine(_resetCoroutine);
        _resetCoroutine = null;
    }
}

5. 添加 DelayedReset 协程

private IEnumerator DelayedReset()
{
    yield return new WaitForSeconds(_resetDelay);
    ResetPlayer();
}

6. 修改 Update 方法

// Check if video has finished playing
if (_mediaPlayer != null && _mediaPlayer.Control != null && 
    _mediaPlayer.Control.IsFinished())
{
    // Reset to beginning but don't auto-play
    _mediaPlayer.Control.Seek(0);
    _mediaPlayer.Pause();
    
    // Update timeline slider
    if (_sliderTime != null)
    {
        _sliderTime.value = 0f;
    }
}

7. 修改 Awake 方法(可选)

void Awake()
{
    #if UNITY_IOS
    Application.targetFrameRate = 60;
    #endif
    
    // 确保在第一次启用时也会重置
    if (_resetOnEnable && enabled && gameObject.activeInHierarchy)
    {
        StartCoroutine(DelayedReset());
    }
}

三、使用说明

1. Inspector 配置

修改后,脚本的 Inspector 面板将显示新的配置选项:

  • Reset On Enable:是否在激活时重置

  • Play On Reset:重置后是否自动播放

  • Reset Delay:重置前的延迟时间(秒)

2. 代码调用

可以通过代码调用 ResetPlayer() 方法手动重置播放器:

GetComponent<MediaPlayerUI>().ResetPlayer();

3. 注意事项

  • 修改后的脚本保留了所有原始功能

  • 重置操作包括:播放位置、音频状态、UI 控件状态

  • 视频播放结束后会自动回到开头并暂停

四、实现原理

  1. 激活重置:通过 OnEnable 触发重置协程

  2. 延迟处理:使用 DelayedReset 协程确保组件完全初始化

  3. 完整重置ResetPlayer 方法处理所有重置逻辑

  4. 播放结束检测:在 Update 中检测播放结束状态

五、适用场景

  • 需要重复播放视频的场景

  • 视频播放器需要频繁激活/禁用的场景

  • 需要精确控制播放初始状态的场景

六、完整代码

// UnityEngine.UI was moved to a package in 2019.2.0
// Unfortunately no way to test for this across all Unity versions yet
// You can set up the asmdef to reference the new package, but the package doesn't 
// existing in Unity 2017 etc, and it throws an error due to missing reference
#define AVPRO_PACKAGE_UNITYUI
#if (UNITY_2019_2_OR_NEWER && AVPRO_PACKAGE_UNITYUI) || (!UNITY_2019_2_OR_NEWER)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using RenderHeads.Media.AVProVideo;
using RenderHeads.Media.AVProVideo.Demos.UI;

//-----------------------------------------------------------------------------
// Copyright 2018-2021 RenderHeads Ltd.  All rights reserved.
//-----------------------------------------------------------------------------

namespace RenderHeads.Media.AVProVideo.Demos
{
    public class MediaPlayerUI : MonoBehaviour
    {
        [SerializeField] MediaPlayer _mediaPlayer = null;

        [Header("Options")]

        [SerializeField] float _keyVolumeDelta = 0.05f;
        [SerializeField] float _jumpDeltaTime = 5f;
        [SerializeField] bool _showOptions = true;
        [SerializeField] bool _autoHide = true;
        [SerializeField] float _userInactiveDuration = 1.5f;
        [SerializeField] bool _useAudioFading = true;

        [Header("Keyboard Controls")]
        [SerializeField] bool _enableKeyboardControls = true;
        [SerializeField] KeyCode KeyVolumeUp = KeyCode.UpArrow;
        [SerializeField] KeyCode KeyVolumeDown = KeyCode.DownArrow;
        [SerializeField] KeyCode KeyTogglePlayPause = KeyCode.Space;
        [SerializeField] KeyCode KeyToggleMute = KeyCode.M;
        [SerializeField] KeyCode KeyJumpForward = KeyCode.RightArrow;
        [SerializeField] KeyCode KeyJumpBack = KeyCode.LeftArrow;

        [Header("Optional Components")]
        [SerializeField] OverlayManager _overlayManager = null;
        [SerializeField] MediaPlayer _thumbnailMediaPlayer = null;
        [SerializeField] RectTransform _timelineTip = null;

        [Header("UI Components")]
        [SerializeField] RectTransform _canvasTransform = null;
        //[SerializeField] Image image = null;
        [SerializeField] Slider _sliderTime = null;
        [SerializeField] EventTrigger _videoTouch = null;
        [SerializeField] CanvasGroup _controlsGroup = null;

        [Header("UI Components (Optional)")]
        [SerializeField] GameObject _liveItem = null;
        [SerializeField] Text _textMediaName = null;
        [SerializeField] Text _textTimeDuration = null;
        [SerializeField] Slider _sliderVolume = null;
        [SerializeField] Button _buttonPlayPause = null;
        [SerializeField] Button _buttonVolume = null;
        [SerializeField] Button _buttonSubtitles = null;
        [SerializeField] Button _buttonOptions = null;
        [SerializeField] Button _buttonTimeBack = null;
        [SerializeField] Button _buttonTimeForward = null;
        [SerializeField] RawImage _imageAudioSpectrum = null;
        [SerializeField] GameObject _optionsMenuRoot = null;
        [SerializeField] HorizontalSegmentsPrimitive _segmentsSeek = null;
        [SerializeField] HorizontalSegmentsPrimitive _segmentsBuffered = null;
        [SerializeField] HorizontalSegmentsPrimitive _segmentsProgress = null;

        private bool _wasPlayingBeforeTimelineDrag;
        private float _controlsFade = 1f;
        private Material _playPauseMaterial;
        private Material _volumeMaterial;
        private Material _subtitlesMaterial;
        private Material _optionsMaterial;
        private Material _audioSpectrumMaterial;
        private float[] _spectrumSamples = new float[128];
        private float[] _spectrumSamplesSmooth = new float[128];
        private float _maxValue = 1f;
        private float _audioVolume = 1f;

        private float _audioFade = 0f;
        private bool _isAudioFadingUpToPlay = true;
        private const float AudioFadeDuration = 0.25f;
        private float _audioFadeTime = 0f;

        private readonly LazyShaderProperty _propMorph = new LazyShaderProperty("_Morph");
        private readonly LazyShaderProperty _propMute = new LazyShaderProperty("_Mute");
        private readonly LazyShaderProperty _propVolume = new LazyShaderProperty("_Volume");
        private readonly LazyShaderProperty _propSpectrum = new LazyShaderProperty("_Spectrum");
        private readonly LazyShaderProperty _propSpectrumRange = new LazyShaderProperty("_SpectrumRange");

        //cyqq
        [Header("Activation Behavior")]
        [Tooltip("Reset playback to beginning when enabled")]
        [SerializeField] bool _resetOnEnable = true;

        [Tooltip("Automatically start playback after reset")]
        [SerializeField] bool _playOnReset = true;

        [Tooltip("Delay before resetting after enable (seconds)")]
        [SerializeField] float _resetDelay = 0.1f;

        private Coroutine _resetCoroutine;

        void Awake()
        {
#if UNITY_IOS
			Application.targetFrameRate = 60;
#endif

            // 确保在第一次启用时也会重置
            if (_resetOnEnable && enabled &