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

news/2025/10/5 22:02:40/文章来源:https://www.cnblogs.com/tlnshuju/p/19127096

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

2025-10-05 21:56  tlnshuju  阅读(0)  评论(0)    收藏  举报

一、功能概述

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

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

二、修改步骤

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() 方法后添加:

/// 
/// Resets the player to beginning and optionally starts playback
/// 
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().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 &

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/928779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dede网站打开慢做采集网站赚钱

旧项目用的 vue3-seamless-scroll 怎么写都不生效&#xff0c;一看源码两年没更新了&#xff0c;不想调试&#xff0c;还是自己写吧&#xff0c;再不济问问GPT都会更快一点 scroll.vue <template><div class"scroll-container" ref"scrollContainerR…

网站做视频的软件营销型网站哪家好

课程背景 2023年&#xff0c;以ChatGPT为代表的接近人类水平的对话机器人&#xff0c;AIGC不断刷爆网络&#xff0c;其强大的内容生成能力给人们带来了巨大的震撼。学术界和产业界也都形成共识&#xff1a;AIGC绝非昙花一现&#xff0c;其底层技术和产业生态已经形成了新的格局…

做损坏文档的网站seo搜索引擎推广

更新Milvus各个组件的配置参数。 调试 您可以在OpenAPI Explorer中直接运行该接口&#xff0c;免去您计算签名的困扰。运行成功后&#xff0c;OpenAPI Explorer可以自动生成SDK代码示例。 ​编辑调试 授权信息 下表是API对应的授权信息&#xff0c;可以在RAM权限策略语句的…

做网站怎么选服务器军队采购网

java中各map中是否可以存储null值情况

linux做网站服务器吗中企动力官网网站

‍ 侯建业 本文由是石科技CIO侯建业撰写并投递参与“数据猿年度金猿策划活动——2023大数据产业年度优秀CIO榜单及奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 是石科技&#xff08;江苏&#xff09;有限公司成立于2021年&#xff0c;由国家超级计算无锡中心与…

nodejs做网站的弊端网站备案中是什么意思

Title: 非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (I) 文章目录 前言I. 从高斯-牛顿法II. 到阻尼高斯-牛顿法III. 再到列文伯格-马夸尔特法1. 列文伯格-马夸尔特法的由来2. 列文伯格-马夸尔特法的说明说明一. 迭代方向说明二. 近似于带权重的梯度…

保险业网站建设想卖产品怎么推广宣传

要使用Python批量根据Excel数据绘制饼状图&#xff0c;可以使用pandas和matplotlib库来实现。以下是一个基本的代码示例&#xff1a; import pandas as pd import matplotlib.pyplot as plt # 读取Excel文件 data pd.read_excel(data.xlsx) # 提取需要用于绘制饼状图的数据列…

网站建设与服务技能实训心得体会采集网站如何收录

一、可继承的属性 1. 文本相关属性 color&#xff1a;文本的颜色。 font-family&#xff1a;字体系列。 font-size&#xff1a;文本的大小。 font-style&#xff1a;文本的样式。 line-height&#xff1a;行与行之间的垂直间距。 2. 列表相关属性 list-style-type&#xff1a;…

uboot 2020版本下gpio命令的使用

1.在uboot命令行中想要支持gpio的命令,需要打开如下宏CONFIG_CMD_GPIO=y2.选用gpio引脚,作为测试引脚 2.1 查看电路原理图,选用那种soc不和mcu连接的pin,这样可以避免mcu的干扰。 2.2 查看pinmux的配置文件pinmux.…

邢台建网站找谁广安做网站

需求&#xff1a; 创建A项目&#xff0c;有函数和类&#xff0c;将A项目生成DLL动态链接库 创建B项目&#xff0c;使用A项目生成的dll和lib相关文件 正常项目开发.h用于函数声明&#xff0c;.cpp用于函数实现&#xff0c;但是项目开发往往不喜欢将.cpp函数实现的代码发给别人&…

网站设计师简历wordpress分类目录模板

按住option之后&#xff0c;点击Enter就可以完成换行操作

网站推广怎么写牡丹江市西安区建设局网站

读 TCP 协议 RFC-793_rfc 793-CSDN博客TCP灌包中RTT时延与RTO超时关系 - konglingbin - 博客园 TCP的RTT算法 从前面的TCP重传机制我们知道Timeout的设置对于重传非常重要。 设长了&#xff0c;重发就慢&#xff0c;丢了老半天才重发&#xff0c;没有效率&#xff0c;性能差&…

C#定时器深度对比:System.Timers.Timer vs System.Threading.Timer性能实测与选型指南 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

盛世华诞 举国同庆|热烈庆祝 LEWISAK 英勇重创消火栓 1 周年!

前情提要:我们在星光灿烂下倾听时代的钟声,我们在漫漫长夜中等待黎明的曙光,多少次,我们心潮难平,多少次,我们辗转难眠,多少次,我们都是为了这不同寻常的一天 —— LEWISAK 重创消火栓 1 周年! ! 望长空,历…

完整教程:<el-table>构建树形结构

完整教程:<el-table>构建树形结构pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monac…

集团企业网站建设文案wordpress图片不清晰

C、Java、JavaScript和python几个语句的对比介绍 C、Java、JavaScript和python语言的for语句 C、Java和JavaScript的for语句的语法类似如下&#xff1a; for (初始条件; 循环条件; 循环后操作) { // 循环体代码 } 初始条件是在进入循环之前执行的语句&#xff0c;初始化循环…

如何在markdown中插入折叠框

rt,我使用的方法比较朴素简单。 直接在markdown中写入html的标签即可,如下: <details> <summary>标题</summary> 内容 </details>就会呈现以下效果:标题 内容

ESP32-C3 Vscode+ESP-IDF开发环境搭建 保姆级教程 - 教程

ESP32-C3 Vscode+ESP-IDF开发环境搭建 保姆级教程 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas…

网站数据模版收费网站推广

为什么80%的码农都做不了架构师&#xff1f;>>> 反正每次来做一个不熟悉的东西&#xff0c;就是各种的search ,前一次去做过一个apache的东西&#xff0c;各种蛋疼&#xff0c;各种不能用。好多的东西也是比较旧了的咯。 这次结合前辈的各种东借西拿&#xff0c;总…

CF2115 VP 记录

CF2115 Div1 B 比较人类智慧. 后面操作会覆盖前面的,考虑对序列 \(b\) 构造一种具有必要性的操作使得满足题目限制,因为一个重要事实是序列 \(a\) 并不唯一,只要对于任意位置,在被覆盖前没有覆盖其他位置的操作,或…