? 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.pswp.cn/pingmian/83080.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83080.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83080.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

5.31 數學復習筆記 22

前面的筆記&#xff0c;全部寫成一段&#xff0c;有點難以閱讀。現在改進一下排版。另外&#xff0c;寫筆記實際上就是圖一個放松呢&#xff0c;關鍵還是在于練習。 目前的計劃是&#xff0c;把講義上面的高數例題搞清楚之后&#xff0c;大量刷練習冊上面的題。感覺不做幾本練…

什么是 WPF 技術?什么是 WPF 樣式?下載、安裝、配置、基本語法簡介教程

什么是 WPF 技術&#xff1f;什么是 WPF 樣式&#xff1f;下載、安裝、配置、基本語法簡介教程 摘要 WPF教程、WPF開發、.NET 8 WPF、Visual Studio 2022 WPF、WPF下載、WPF安裝、WPF配置、WPF樣式、WPF樣式詳解、XAML語法、XAML基礎、MVVM架構、數據綁定、依賴屬性、資源字典…

ROS2與Unitree機器人集成指南

Tested systems and ROS2 distro systemsROS2 distroUbuntu 20.04foxyUbuntu 22.04humblesrc目錄上級才可以colcon build git clone https://github.com/unitreerobotics/unitree_ros2 Install Unitree ROS2 package 1. Dependencies sudo apt install ros-humble-rmw-cyclon…

深入探討集合與數組轉換方法

目錄 1、Arrays.asList() 1.1、方法作用 1.2、內部實現 1.3、修改元素的影響 1.4、注意事項 2、list.toArray() 2.1、方法作用 2.2、內部實現 2.3、修改元素的影響 2.4、特殊情況 1、對象引用 2、數組copy 3、對比總結 4、常見誤區與解決方案 5、實際應用建議…

深入理解交叉熵損失函數——全面推演各種形式

帶你從不一樣的視角綜合認識交叉熵損失&#xff0c;閱讀這篇文章&#xff0c;幫你建立其分類問題&#xff0c;對比學習&#xff0c;行人重識別&#xff0c;人臉識別等問題的聯系&#xff0c;閱讀這篇文章相信對你閱讀各種底層深度學習論文有幫助。 引言 1. 重新理解全連接層&…

STM32之FreeRTOS移植(重點)

RTOS的基本概念 實時操作系統&#xff08;Real Time Operating System&#xff09;的簡稱就叫做RTOS&#xff0c;是指具有實時性、能支持實時控制系統工作的操作系統&#xff0c;RTOS的首要任務就是調度所有可以利用的資源來完成實時控制任務的工作&#xff0c;其次才是提高工…

MySQL connection close 后, mysql server上的行為是什么

本文著重講述的是通過 msql client 連接到 mysql server &#xff0c;發起 update 、 select 操作(由于數據量非常大&#xff0c;所以 update、select 操作都很耗時&#xff0c;即在結果返回前我們有足夠的時間執行一些操作) 。 在客戶端分別嘗試執行 ctrl C 結束關閉 mysql c…

dvwa3——CSRF

LOW&#xff1a; 先嘗試change一組密碼&#xff1a;123456 修改成功&#xff0c;我們觀察上面的url代碼 http://localhost/DVWA/vulnerabilities/csrf/?password_new123456&password_conf123456&ChangeChange# 將password_new部分與password_conf部分改成我們想要的…

Linux 中常見的安全與權限機制

Linux 中常見的安全與權限機制主要包括以下幾類&#xff0c;從文件系統權限到系統級訪問控制&#xff0c;構建了多層次的安全保障體系。 &#x1f510; 一、文件權限與用戶管理 1. 基本權限&#xff08;rwx&#xff09; r&#xff08;read&#xff09;&#xff1a;讀取文件內…

CSS篇-3

1. CSS 中哪些樣式可以繼承&#xff1f;哪些不可以繼承&#xff1f; 可繼承的樣式&#xff1a; 與字體相關的樣式&#xff0c;如&#xff1a;font-size、font-family、color 列表樣式&#xff1a;list-style&#xff08;如 UL、OL 的 list-style-type&#xff09; 不可繼承…

計算機網絡物理層基礎練習

第二章 物理層 填空題 從通信雙方信息交互的方式來看&#xff0c;通信的三種基本方式為單工、半雙工和全雙工。其中&#xff0c;單工數據傳輸只支持數據在一個方向上傳輸&#xff0c;全雙工數據傳輸則允許數據同時在兩個方向上傳輸。最基本的帶通調制方法包括三種&#xff1a…

Redis7底層數據結構解析

redisObject 在 Redis 的源碼中&#xff0c;Redis 會將底層數據結構&#xff08;如 SDS、hash table、skiplist 等&#xff09;統一封裝成一個對象&#xff0c;這個對象叫做 redisObject&#xff0c;也簡稱 robj。 typedef struct redisObject {unsigned type : 4; // 數…

華為OD機試_2025 B卷_靜態掃描(Python,100分)(附詳細解題思路)

題目描述 靜態掃描可以快速識別源代碼的缺陷&#xff0c;靜態掃描的結果以掃描報告作為輸出&#xff1a; 1、文件掃描的成本和文件大小相關&#xff0c;如果文件大小為N&#xff0c;則掃描成本為N個金幣 2、掃描報告的緩存成本和文件大小無關&#xff0c;每緩存一個報告需要…

【Java】在 Spring Boot 中連接 MySQL 數據庫

在 Spring Boot 中連接 MySQL 數據庫是一個常見的任務。Spring Boot 提供了自動配置功能&#xff0c;使得連接 MySQL 數據庫變得非常簡單。以下是詳細的步驟&#xff1a; 一、添加依賴 首先&#xff0c;確保你的pom.xml文件中包含了 Spring Boot 的 Starter Data JPA 和 MySQ…

基于51單片機的音樂盒鍵盤演奏proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1tZCAxQQ7cvyzBfztQpk0UA 提取碼&#xff1a;1234 仿真圖&#xff1a; 芯片/模塊的特點&#xff1a; AT89C52/AT89C51簡介&#xff1a; AT89C51 是一款常用的 8 位單片機&#xff0c;由 Atmel 公司&#xff08;現已被 Microchip 收…

Android Native 之 adbd進程分析

目錄 1、adbd守護進程 2、adbd權限降級 3、adbd命令解析 1&#xff09;adb shell 2&#xff09;adb root 3&#xff09;adb reboot 4、案例 1&#xff09;案例之實現不需要執行adb root命令自動具有root權限 2&#xff09;案例之實現不需要RSA認證直接能夠使用adb she…

C語言進階--動態內存管理

學習數據結構重要的三個部分&#xff1a;指針、結構體、動態內存管理&#xff08;malloc、calloc、realloc、free&#xff09;。 1.為什么存在動態內存分配&#xff1f; 1.空間開辟大小是固定的&#xff1b; 2.數組在聲明時&#xff0c;必須指定數組的長度&#xff0c;它所需…

C# 密封類和密封方法

密封(sealed)是C#中用于限制繼承和多態行為的關鍵字&#xff0c;它可以應用于類和方法&#xff0c;提供了一種控制繼承層次的方式。 密封類 特點 使用 sealed 關鍵字修飾的類密封類不能被其他類繼承&#xff0c;但可以繼承其他類或接口主要用于防止派生所有結構(struct)都是…

thinkpad T-440p 2025.05.31

thinkpad T-440p 2025.05.31 老了退休了&#xff0c;說起來真的可惡現在筆記本的設計師&#xff0c;只有固態硬盤了

WPS自動換行

換行前 換行后 快捷鍵 第一步&#xff1a;啟用「自動換行」功能 選中目標單元格/區域&#xff1a;點擊需要設置的單元格&#xff08;或拖動選中多個單元格&#xff09;。開啟自動換行&#xff08;3種方式任選&#xff09;&#xff1a; 快捷按鈕&#xff1a;在頂部菜單欄點擊「…