当前位置: 首页 > ai >正文

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

一、功能概述

本笔记记录直接修改插件自带的场景播放其中 原始的 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 UIUpdateVolumeSlider();// Start playback if configured to do soif (_playOnReset){_mediaPlayer.Play();// Trigger play feedback if overlay manager existsif (_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 sliderif (_sliderTime != null){_sliderTime.value = 0f;}
}

3. 修改/添加 OnEnable 方法

private void OnEnable()
{if (_resetOnEnable){// Start reset coroutine with small delay to ensure everything is initializedif (_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 sliderif (_sliderTime != null){_sliderTime.value = 0f;}
}

7. 修改 Awake 方法(可选)

void Awake()
{#if UNITY_IOSApplication.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_IOSApplication.targetFrameRate = 60;
#endif// 确保在第一次启用时也会重置if (_resetOnEnable && enabled &
http://www.xdnf.cn/news/9998.html

相关文章:

  • 在日常管理服务器中如何防止SQL注入与XSS攻击?
  • STM32G4 电机外设篇(二) VOFA + ADC + OPAMP
  • CloudCompare-源码分析-处理滚轮事件
  • 【Elasticsearch】suggest_mode
  • LangChain整合Milvus向量数据库实战:数据新增与删除操作
  • Centos7.x内网环境Jenkins前端打包环境配置
  • C#定时器深度对比:System.Timers.Timer vs System.Threading.Timer性能实测与选型指南
  • PECVD 生成 SiO₂ 的反应方程式
  • 数据分类分级的实践与反思:源自数据分析、治理与安全交叉视角的洞察
  • Python训练day34
  • LangChain-LangGraph框架 应用实例
  • 超低延迟与高稳定性的行业领先直播解决方案
  • RocketMQ 三大消息类型深度解析:普通消息、延迟消息、事务消息
  • C++ —— B/类与对象(中)
  • Python字典键的使用与应用:从基础到高级实践
  • OCC笔记:BRepMesh_IncrementalMesh的使用
  • python打卡day40@浙大疏锦行
  • 汽车高速通信的EMC挑战
  • Langchain4j Function Calling (5)
  • 关于ffplay在macos上运行奔溃的问题
  • 嵌入式开发学习日志(linux系统编程--进程(4)——线程锁)Day30
  • Google car key:安全、便捷的汽车解锁新选择
  • day40打卡
  • Netty 实战篇:为 Netty RPC 框架引入调用链追踪,实现链路透明化
  • 特伦斯 S75 电钢琴:奏响音乐新时代的华章
  • mongodb集群之分片集群
  • Ubuntu 22.04 系统下 Docker 安装与配置全指南
  • Android JNI开发
  • 大语言模型的技术原理与应用前景:从Transformer到ChatGPT
  • 技术原理简析:卫星遥感如何感知水体环境?