【Unity筆記】Unity音視頻播放監聽器封裝筆記:VideoPlayer + AudioSource事件觸發與編輯器擴展

關鍵點

  • Unity VideoPlayer 播放結束事件
  • Unity AudioSource 播放檢測

在這里插入圖片描述

Unity音視頻播放監聽器封裝筆記:VideoPlayer + AudioSource事件觸發與編輯器擴展

在 Unity 的多媒體開發中,我們經常需要監聽 VideoPlayerAudioSource 的播放狀態,以便在開始播放或播放結束時觸發一系列操作,例如切換 UI、播放動畫、調用某腳本的方法等。

為了提升開發效率與復用性,本文記錄如何封裝 可復用、可配置、可掛載 UnityEvent 的監聽器組件,并通過 自定義 Inspector 實現良好的編輯器體驗。


1. 監聽 VideoPlayer 播放事件并觸發腳本方法

Unity 的 VideoPlayer 提供了兩個關鍵事件:

  • started:視頻開始播放
  • loopPointReached:視頻播放完成(非循環模式)

我們封裝一個腳本 VideoPlayerEventListener.cs 來監聽上述事件,并掛載 UnityEvent,供你在 Inspector 中拖拽執行目標方法(如 腳本A.Exec())。

VideoPlayerEventListener.cs

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Video;[RequireComponent(typeof(VideoPlayer))]
public class VideoPlayerEventListener : MonoBehaviour
{[Header("視頻開始播放時觸發")]public UnityEvent onVideoStarted;[Header("視頻播放完成時觸發")]public UnityEvent onVideoEnded;private VideoPlayer videoPlayer;private bool hasStarted = false;void Awake(){videoPlayer = GetComponent<VideoPlayer>();}void OnEnable(){videoPlayer.started += OnVideoStarted;videoPlayer.loopPointReached += OnVideoEnded;}void OnDisable(){videoPlayer.started -= OnVideoStarted;videoPlayer.loopPointReached -= OnVideoEnded;}private void OnVideoStarted(VideoPlayer vp){if (!hasStarted){hasStarted = true;onVideoStarted?.Invoke();}}private void OnVideoEnded(VideoPlayer vp){hasStarted = false;onVideoEnded?.Invoke();}
}

2. 自定義 Inspector 提升編輯器體驗

為了讓 UnityEvent 在 Inspector 中更直觀易用,我們還封裝了一個自定義編輯器:

VideoPlayerEventListenerEditor.cs

using UnityEditor;
using UnityEngine;[CustomEditor(typeof(VideoPlayerEventListener))]
public class VideoPlayerEventListenerEditor : Editor
{SerializedProperty onVideoStarted;SerializedProperty onVideoEnded;void OnEnable(){onVideoStarted = serializedObject.FindProperty("onVideoStarted");onVideoEnded = serializedObject.FindProperty("onVideoEnded");}public override void OnInspectorGUI(){serializedObject.Update();var videoPlayer = (target as VideoPlayerEventListener).GetComponent<UnityEngine.Video.VideoPlayer>();if (videoPlayer == null){EditorGUILayout.HelpBox("缺少 VideoPlayer 組件。", MessageType.Error);}else{EditorGUILayout.HelpBox("監聽 VideoPlayer 播放狀態,并觸發 UnityEvent。", MessageType.Info);EditorGUILayout.PropertyField(onVideoStarted, new GUIContent("🎬 視頻開始播放"));EditorGUILayout.PropertyField(onVideoEnded, new GUIContent("🏁 視頻播放結束"));}serializedObject.ApplyModifiedProperties();}
}

將此腳本放入 Editor 文件夾中即可自動生效。


3. 監聽 AudioSource 音頻播放狀態

不同于 VideoPlayerAudioSource 并沒有原生的播放完成事件。因此我們通過 Update() 方法持續檢測播放狀態,并提供播放進度(progress)供 UI 顯示。

AudioSourceEventListener.cs

using UnityEngine;
using UnityEngine.Events;[RequireComponent(typeof(AudioSource))]
public class AudioSourceEventListener : MonoBehaviour
{[Header("音頻開始播放時觸發")]public UnityEvent onAudioStarted;[Header("音頻播放完成時觸發")]public UnityEvent onAudioEnded;[Range(0f, 1f), Tooltip("當前播放進度 (僅查看)")]public float progress;private AudioSource audioSource;private bool hasStarted = false;private bool hasEnded = false;void Awake(){audioSource = GetComponent<AudioSource>();}void Update(){if (audioSource.clip == null)return;if (!hasStarted && audioSource.isPlaying){hasStarted = true;hasEnded = false;onAudioStarted?.Invoke();}if (audioSource.isPlaying){progress = audioSource.time / audioSource.clip.length;}if (hasStarted && !audioSource.isPlaying && !hasEnded && audioSource.time >= audioSource.clip.length){hasEnded = true;onAudioEnded?.Invoke();}}
}

AudioSourceEventListenerEditor.cs

using UnityEditor;
using UnityEngine;[CustomEditor(typeof(AudioSourceEventListener))]
public class AudioSourceEventListenerEditor : Editor
{SerializedProperty onAudioStarted;SerializedProperty onAudioEnded;SerializedProperty progress;void OnEnable(){onAudioStarted = serializedObject.FindProperty("onAudioStarted");onAudioEnded = serializedObject.FindProperty("onAudioEnded");progress = serializedObject.FindProperty("progress");}public override void OnInspectorGUI(){serializedObject.Update();EditorGUILayout.HelpBox("監聽 AudioSource 播放狀態,并觸發 UnityEvent。", MessageType.Info);EditorGUILayout.PropertyField(onAudioStarted, new GUIContent("🎧 音頻開始播放"));EditorGUILayout.PropertyField(onAudioEnded, new GUIContent("🏁 音頻播放結束"));EditorGUILayout.Space();EditorGUILayout.LabelField("📊 播放進度", EditorStyles.boldLabel);EditorGUI.ProgressBar(EditorGUILayout.GetControlRect(), progress.floatValue, $"{(progress.floatValue * 100f):0.0}%");serializedObject.ApplyModifiedProperties();}
}

4. 使用示例

  1. 在一個 GameObject 上添加 VideoPlayerEventListenerAudioSourceEventListener
  2. 選擇你需要監聽的事件(開始/結束)。
  3. 點擊 + 添加響應函數(如某個腳本的 Exec() 方法)。
  4. 運行時自動回調,不需要手動注冊監聽器。

5.總結與拓展建議

通過以上封裝,我們實現了可復用的播放監聽邏輯,統一用 UnityEvent 掛載,完全無需寫代碼也能實現播放回調,特別適合策劃/UI 場景中使用。

📌 推薦進一步拓展:

  • 播放進度回調事件(支持 float 參數)。
  • 播放完自動播放下一個文件。
  • 可視化播放進度 UI(Slider/圓環等)。
  • 支持 AssetBundle 動態加載音視頻資源。

6. 結語

音視頻播放作為交互中重要的一環,其狀態監聽和回調封裝將極大提升項目開發效率。希望這套封裝組件可以幫助你打造更高效、模塊化的多媒體播放系統。

如果你覺得有幫助,歡迎點贊、收藏并關注!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76630.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76630.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76630.shtml

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

相關文章

WPF常用技巧匯總

主要用于記錄工作中發現的一些問題和常見的解決方法。 此文會持續更新。 >abp new Evan.MyWpfApp -t wpf --old --framework .net8 1. 解決不同屏幕分辨率下的鋸齒問題 UseLayoutRounding"True" <Grid UseLayoutRounding"True"><Border Mar…

分數線降低,25西電馬克思主義學院(考研錄取情況)

1、馬克思主義學院各個方向 2、馬克思主義學院近三年復試分數線對比 學長、學姐分析 由表可看出&#xff1a; 1、馬克思主義理論25年相較于24年下降10分&#xff0c;為355分 3、25vs24推免/統招人數對比 學長、學姐分析 由表可看出&#xff1a; 1、 馬克思主義學院25年共接…

【Linux網絡】構建UDP服務器與字典翻譯系統

&#x1f4e2;博客主頁&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客倉庫&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;歡迎點贊 &#x1f44d; 收藏 ?留言 &#x1f4dd; 如有錯誤敬請指正&#xff01; &…

【項目管理】成本類計算 筆記

項目管理-相關文檔&#xff0c;希望互相學習&#xff0c;共同進步 風123456789&#xff5e;-CSDN博客 &#xff08;一&#xff09;知識總覽 項目管理知識域 知識點&#xff1a; &#xff08;項目管理概論、立項管理、十大知識域、配置與變更管理、績效域&#xff09; 對應&…

div(HTML標準元素)和view(微信小程序專用組件)的主要區別體

div&#xff08;HTML標準元素&#xff09;和view&#xff08;微信小程序專用組件&#xff09;的主要區別體現在以下方面&#xff1a; 一、應用場景與開發框架 ?適用平臺不同? div是HTML/CSS開發中通用的塊級元素&#xff0c;用于Web頁面布局?&#xff1b;view是微信小程序專…

【C++軟件實戰問題排查經驗分享】UI界面卡頓 | CPU占用高 | GDI對象泄漏 | 線程堵塞 系列問題排查總結

目錄 1、UI界面卡頓問題排查 2、軟件CPU占用高問題排查 3、UI界面顯示異常&#xff08;GDI對象泄漏導致窗口繪制異常&#xff09;問題排查 4、軟件線程堵塞&#xff08;包含線程死鎖&#xff09;問題排查 5、最后 C軟件異常排查從入門到精通系列教程&#xff08;核心精品專…

管理雜談——采石磯大捷的傳奇與啟示

南宋抗金史上&#xff0c;岳飛與岳家軍的鐵血傳奇家喻戶曉&#xff0c;但另一位力挽狂瀾的“文官戰神”卻常被忽視——他從未掌兵&#xff0c;卻在南宋存亡之際整合潰軍&#xff0c;以少勝多&#xff0c;締造采石磯大捷。此人正是虞允文。一介書生何以扭轉乾坤&#xff1f;他的…

動態規劃-零錢兌換

332.零錢兌換 給你一個整數數組 coins &#xff0c;表示不同面額的硬幣&#xff1b;以及一個整數 amount &#xff0c;表示總金額。計算并返回可以湊成總金額所需的 最少的硬幣個數 。如果沒有任何一種硬幣組合能組成總金額&#xff0c;返回 -1 。你可以認為每種硬幣的數量是無…

SpringAI+DeepSeek大模型應用開發——4 對話機器人

目錄??????? ??????????????項目初始化 pom文件 配置模型 ChatClient 同步調用 流式調用 日志功能 對接前端 解決跨域 會話記憶功能 ChatMemory 添加會話記憶功能 會話歷史 管理會話id 保存會話id 查詢會話歷史 完善會話記憶 定義可序列…

Java 關鍵字

本章列出了Java 語言的所有關鍵字和“類關鍵字的單詞”。 “受限關鍵字”是指&#xff0c;它們旨在模塊聲明中是關鍵字&#xff0c;在其他情況下則是標識符。 “受限標識符”是指&#xff0c;除非用在某些特定位置&#xff0c;否則他們只是標識符。例如&#xff0c;var一般都…

AI重塑網絡安全:機遇與威脅并存的“雙刃劍”時代

一、引言 人工智能&#xff08;AI&#xff09;技術的迅猛發展&#xff0c;正在深刻改變網絡安全行業的格局。從ChatGPT生成釣魚郵件到AI驅動的漏洞挖掘&#xff0c;從零信任架構的普及到安全大模型的實戰應用&#xff0c;AI既是攻擊者的“新武器”&#xff0c;也是防御者的“新…

網絡原理——UDP

1、 與TCP的關鍵區別 特性UDPTCP連接方式無連接面向連接可靠性不可靠可靠數據順序不保證順序保證順序傳輸速度更快相對較慢頭部開銷8字節20-60字節流量控制無有擁塞控制無有適用場景實時應用、廣播/多播可靠性要求高的應用 2、UDP 報文結構 報文結構大致可以分為首部和載荷&a…

STM32——新建工程并使用寄存器以及庫函數進行點燈

本文是根據江協科技提供的教學視頻所寫&#xff0c;旨在便于日后復習&#xff0c;同時供學習嵌入式的朋友們參考&#xff0c;文中涉及到的所有資料也均來源于江協科技&#xff08;資料下載&#xff09;。 新建工程并使用寄存器以及庫函數進行點燈操作 新建工程步驟1.建立工程2.…

Unocss 類名基操, tailwindcss 類名

這里只列出 unocss 的可實現類名&#xff0c;tailwindcss 可以拿去試試用 1. 父元素移入&#xff0c;子元素改樣式 <!-- 必須是 group 類名 --> <div class"group"><div class"group-hover:color-red">Text</div> </div>2…

深度學習入門(一)

一、簡介 深度學習是機器學習領域新興且關鍵的研究方向。機器學習重點在于讓計算機從數據中挖掘規律以預測未知&#xff0c;而深度學習借助構建多層神經網絡&#xff0c;自動學習數據的復雜特征&#xff0c;從而實現更精準的模式識別&#xff0c;在圖像、語音等眾多領域廣泛應…

element-plus中,Steps 步驟條組件的使用

目錄 一.基本使用 1.代碼 2.效果展示 3.代碼解讀 二.案例&#xff1a;修改用戶的密碼 1.期望效果 2.代碼 3.展示效果 結語 一.基本使用 1.代碼 從官網復制如下代碼&#xff1a; <template><div><el-stepsstyle"max-width: 600px":space&quo…

jax 備忘錄

https://zhuanlan.zhihu.com/p/532504225 https://docs.jax.dev/en/latest/index.html

NLTK 基礎入門:用 Python 解鎖自然語言處理

自然語言處理&#xff08;NLP&#xff09;是人工智能領域的重要分支&#xff0c;它讓計算機能夠理解、處理和生成人類語言。而 NLTK&#xff08;Natural Language Toolkit&#xff09; 作為 Python 生態中最經典的 NLP 庫之一&#xff0c;提供了豐富的工具和資源&#xff0c;是…

ElementUI中checkbox v-model綁定值為布爾、字符串或數字類型

這篇博客介紹了在Vue.js中使用El-Checkbox組件時&#xff0c;如何設置和處理v-model的布爾值和類型轉換。通過示例代碼展示了如何設置true-label和false-label屬性來改變選中狀態的值&#xff0c;適用于需要特定類型&#xff08;如字符串或整數&#xff09;的場景。v-model不能…

JBoss 項目修復筆記:繞開 iframe 安全問題,JSF 與 Angular 最小代價共存方案

JBoss 項目修復筆記&#xff1a;繞開 iframe 安全問題&#xff0c;JSF 與 Angular 最小代價共存方案 本篇筆記銜接的內容為&#xff1a;JBoss WildFly 本地開發環境完全指南&#xff0c;里面簡單的描述了一下怎么配置 docker&#xff0c;在本地啟動一個可以運行的 JBoss 和 W…