一.進度條播放視頻
相關代碼
using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; public class ToPlayVideo : MonoBehaviour { public VideoClip[] videoClips; // 視頻的文件 參數 public Text videoTimeText; // 視頻的當前時間 Text public Text videoNameText; // 視頻的總時長 Text public Slider videoTimeSlider; // 視頻的時間 Slider // 定義參數獲取VideoPlayer組件和RawImage組件 internal VideoPlayer videoPlayer; public RawImage rawImage;//拖入的方式更好。新建一個RawImage public Texture pingBao; // 屏保圖片 // 當前視頻的總時間值和當前播放時間值的參數 private int currentHour; private int currentMinute; private int currentSecond; private int clipHour; private int clipMinute; private int clipSecond; public Sprite play; public Sprite pause; private bool isPlay = true; //是否正在播放視頻 public Button playPauseButton; //播放暫停按鈕 public Button stopButton; //停止播放按鈕
public Slider SoundSlider;
public AudioSource VideoSound;
public Button button1;//多個視頻 public Button button2; public Button button3; public Button button4; // Use this for initialization void Start() { //清空文本 videoNameText.text = ""; videoTimeText.text = ""; //獲取場景中對應的組件 videoPlayer = this.GetComponent<VideoPlayer>(); // rawImage = this.GetComponent<RawImage>(); videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource; videoPlayer.SetTargetAudioSource(0, this.GetComponent<AudioSource>()); videoPlayer.playOnAwake = false; videoPlayer.IsAudioTrackEnabled(0); playPauseButton.onClick.AddListener(PlayOrPause); stopButton.onClick.AddListener(StopVideo);
SoundSlider.onValueChanged.AddListener(OnVolume); button1.onClick.AddListener(delegate { OnClick(0); }); button2.onClick.AddListener(delegate { OnClick(1); }); button3.onClick.AddListener(delegate { OnClick(2); }); button4.onClick.AddListener(delegate { OnClick(3); }); } // Update is called once per frame void Update() { //如果videoPlayer沒有對應的視頻texture,則返回屏保 if (videoPlayer.texture == null) { rawImage.texture = pingBao; return; } //把VideoPlayerd的視頻渲染到UGUI的RawImage rawImage.texture = videoPlayer.texture; ShowVideoTime(); }
///音量控制 private void OnVolume(float value)
{
VideoSound.volume=value;
} /// <summary> /// 顯示當前視頻的時間 /// </summary> private void ShowVideoTime() { // 當前的視頻播放時間 currentHour = (int)videoPlayer.time / 3600; currentMinute = (int)(videoPlayer.time - currentHour * 3600) / 60; currentSecond = (int)(videoPlayer.time - currentHour * 3600 - currentMinute * 60); // 把當前視頻播放的時間顯示在 Text 上 videoTimeText.text = string.Format("{0:D2}:{1:D2}:{2:D2}", currentHour, currentMinute, currentSecond); // 把當前視頻播放的時間比例賦值到 Slider 上 videoTimeSlider.value = (float)(videoPlayer.time / videoPlayer.clip.length); } /// <summary> /// 顯示視頻的總時長 /// </summary> /// <param name="videos">當前視頻</param> void ShowVideoLength(VideoClip videos) { videoPlayer.clip = videos; videoPlayer.Play(); videoTimeSlider.gameObject.SetActive(true); clipHour = (int)videoPlayer.clip.length / 3600; clipMinute = (int)(videoPlayer.clip.length - clipHour * 3600) / 60; clipSecond = (int)(videoPlayer.clip.length - clipHour * 3600 - clipMinute * 60); videoNameText.text = string.Format("{0:D2}:{1:D2}:{2:D2} ", clipHour, clipMinute, clipSecond); } private void OnClick(int num) { switch (num) { case 0: ShowVideoLength(videoClips[0]); break; case 1: ShowVideoLength(videoClips[1]); break; case 2: ShowVideoLength(videoClips[2]); break; case 3: ShowVideoLength(videoClips[3]); break; case 4: ShowVideoLength(videoClips[4]); break; default: break; } } /// <summary> /// 視頻播放暫停 /// </summary> void PlayOrPause() { //如果視頻片段不為空,並且視頻畫面沒有播放完畢 if (videoPlayer.clip != null && (ulong)videoPlayer.frame < videoPlayer.frameCount)//黃色部分可以隱藏測試 { //如果視頻正在播放 if (isPlay) { playPauseButton.image.sprite = pause; videoPlayer.Pause(); isPlay = false; } else { playPauseButton.image.sprite = play; videoPlayer.Play(); isPlay = true; } } } void StopVideo() { videoPlayer.Stop(); playPauseButton.image.sprite = play; videoTimeSlider.gameObject.SetActive(false); videoNameText.text = ""; videoTimeText.text = ""; isPlay = true; } }
using UnityEngine; using UnityEngine.EventSystems; /// <summary> /// 繼承 拖拽接口 /// </summary> public class SliderEvent : MonoBehaviour, IDragHandler, IEndDragHandler { [SerializeField] public ToPlayVideo toPlayVideo; // 視頻播放的腳本 // Use this for initialization void Start() {
//2022.2.9新增
UnityUtility.AddTriggersListener(toPlayVideo.videoTimeSlider.gameObject, EventTriggerType.Drag,OnSliderDrage);
UnityUtility.AddTriggersListener(toPlayVideo.videoTimeSlider.gameObject, EventTriggerType.EndDrag,OnSliderEndDrage);
}
//2022.2.9新增 視頻進度條開始拖拽
private void OnSliderDrage(BaseEventDate arg0)
{
toPlayVideo.videoPlayer.Pause();
SetVideoTimeValueChange();
}
//2022.2.9新增 視頻進度條結束拖拽
private void OnSliderEndDrage(BaseEventDate arg0)
{
toPlayVideo.videoPlayer.Play();
}
// Update is called once per frame void Update() { } /// <summary> /// 給 Slider 添加開始拖拽事件 /// </summary> /// <param name="eventData"></param> public void OnDrag(PointerEventData eventData) { toPlayVideo.videoPlayer.Pause(); SetVideoTimeValueChange(); } /// <summary> /// 當前的 Slider 比例值轉換為當前的視頻播放時間 /// </summary> private void SetVideoTimeValueChange() { toPlayVideo.videoPlayer.time = toPlayVideo.videoTimeSlider.value * toPlayVideo.videoPlayer.clip.length; } /// <summary> /// 給 Slider 添加結束拖拽事件 /// </summary> /// <param name="eventData"></param> public void OnEndDrag(PointerEventData eventData) { toPlayVideo.videoPlayer.Play(); } }
一些button 監聽到是很容易,一些OnClick可以滿足,但是像Slider 有點繁瑣 大體是這樣的
using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; using System.Text; public static class UnityUtility { public static void AddTriggersListener(GameObject obj, EventTriggerType eventID, UnityAction<BaseEventData> action) { EventTrigger trigger = obj.GetComponent<EventTrigger>(); if (trigger == null) { trigger = obj.AddComponent<EventTrigger>(); } if (trigger.triggers.Count == 0) { trigger.triggers = new List<EventTrigger.Entry>(); } UnityAction<BaseEventData> callback = new UnityAction<BaseEventData>(action); EventTrigger.Entry entry = new EventTrigger.Entry(); entry.eventID = eventID; entry.callback.AddListener(callback); trigger.triggers.Add(entry); } }
如何使用呢?
UnityUtility.AddTriggersListener(需要綁定的物體, EventTriggerType 類型, 回調方法);
UnityUtility.AddTriggersListener(strengthSlider.gameObject, EventTriggerType.Drag, OnStrengSliderSelcet);
那么如何刪除呢?
if (strengthSlider.GetComponent<EventTrigger>())
{undefined
EventTrigger trigger = strengthSlider.GetComponent<EventTrigger>();
trigger.triggers.RemoveAll(p => true);
}
這里是全部刪除了
slider腳本上添加監聽
onValueChanged.AddListener(方法名或用Lambda表達式)
public Slider slider; void Awake() { slider.GetComponent<Slider>().onValueChanged.AddListener(ValueChanged); } private void ValueChanged(float value) { //邏輯處理 }
或
public Slider slider; void Awake() { slider.GetComponent<Slider>().onValueChanged.AddListener((float value) => { //邏輯處理 }); }
VedioPlayer Source問題(無法拖入資源)
Source:選擇視頻的來源類型
參數選擇:
1.Video Clip:將Video Clip分配給Video Player。使用Video Clip字段定義分配給VideoPlayer組件的Video Clip.將視頻文件拖放到此字段中,或單擊該字段右側的圓圈,然后從Asset中選擇它,如果它位於Project文件夾中。
2.URL:通過URL分配視頻(例如:http://或者file://).Unity通過URL在運行時讀取視頻。使用URL字段輸入要分配給VideoPlayer的視頻URL.可以單擊Browse...快速瀏覽本地文件系統並打開以flie://開頭的URL.
Source:選擇視頻的來源類型
參數選擇:
1.Video Clip:將Video Clip分配給Video Player。使用Video Clip字段定義分配給VideoPlayer組件的Video Clip.將視頻文件拖放到此字段中,或單擊該字段右側的圓圈,然后從Asset中選擇它,如果它位於Project文件夾中。
2.URL:通過URL分配視頻(例如:http://或者file://).Unity通過URL在運行時讀取視頻。使用URL字段輸入要分配給VideoPlayer的視頻URL.可以單擊Browse...快速瀏覽本地文件系統並打開以flie://開頭的URL.
Play On Awake:勾選Play On Awake,在Scene啟動時播放視頻。若想自己控制視頻什么時候播放,則不需要勾選。使用Play()命令通過腳本觸發它。
Wait For First Frame:如果你勾選Wait For First Frame復選框,Unity會在游戲開始前等待源視頻的第一幀准備好顯示。如果取消勾選,可能會丟棄前幾幀以使視頻時間與游戲的其余部分保持同步。
Loop:勾選Loop使Video Player組件在視頻播放完后重復播放。如果沒有勾選,當視頻播放完就會停止播放。
Playback Speed:此滑塊和數字字段表示播放速度的乘數,為0到10之間的值。默認設置為1(正常速度)。如果設置為2,視頻的播放速度就是正常情況下的兩倍。
Render Mode:使用下拉列表定義視頻的渲染方式。
參數選擇:
1.Camera Far Plane:在Camera's far plane渲染視頻。並設置渲染視頻的camera,通過Alpha設置全局透明度級別添加到源視頻中。這允許通過它可以看到平面后面的元素。
2.Camera Near Plane:在Camera's near plane渲染視頻。並設置渲染視頻的camera,通過Alpha設置全局透明度級別添加到源視頻中。這允許通過它可以看到平面后面的元素。
3.Render Texture:將視頻渲染為Render Texture.通過設置Target Texture定義Render Texture組件渲染其圖像的“Render Texture”.
4.Material Override:通過Renderer's Material的將視頻渲染到GameObject選定的Texture屬性中。通過設置Renderer來設置Video Player組件渲染它的圖像的Renderer.不設置的話,將使用與Video Player相同GameObject上的Renderer。通過設置Material Property來設置接收Video Player組件圖像的材質紋理屬性的名稱。
5.API Only:將視頻渲染到VideoPlayer.texture屬性中。你必須使用腳本將紋理指定給其預期目標。
Aspect Ratio:使用相應渲染模式時,填充Camera Near Plane,Camera Far Plane或者Render的圖像的寬高比。
參數選擇:
1.No Scaling:沒有使用縮放。視頻以目標矩形為中心。
2.Fit Vertically:縮放視頻以垂直適應目標矩形,裁剪左側和右側或在必要時在每側留下黑色區域。視頻的橫縱比保留。
3.Fit Horzontally:縮放視屏以水平適應目標矩形,裁剪頂部和底部區域或在需要時在上方和下方留下黑色區域。視頻的橫縱比保留。
4.Fit Inside:縮放視頻以適合目標矩形,而不必裁剪。根據需要在左側和右側或上方和下放留下黑色區域。視頻的橫縱比保留。
5.Fit OutSide:縮放視頻以適合目標矩形,而不會在左側和右側或上方和下放留下黑色區域,根據需要進行裁剪。視頻的橫縱比保留。
6.Stretch:水平或垂直縮放以適合目標矩形。視屏的橫縱比不會保留。
Audio Output Mode:定義如何輸出源的音軌。
參數選擇:
1.None:音頻不播放
2.Audio Source:音頻樣本被發送到制定的audio sources,從而可以應用Unity的音頻處理。
3.Direct:音頻樣本直接發送到音頻輸出硬件,繞過unity的音頻處理。
Controlled Tracks:視頻中的音軌數量。當Source選擇URL時才會顯示。當Source時Video Clip時,通過檢查視頻文件來確定軌道數。
Track Enabled:通過勾選相關復選框啟用時,相關的音軌用於播放。必須在播放前設置此項。復選框左側的文本提供有關音軌的信息,特別是曲目編號,語言和頻道數。例如在上面的截圖中,這個文本是Track 0[und.1 ch].這意味着它是第一首曲目(曲目0),語言未定義(und.),曲目有一個頻道(1ch),這意味着它是單聲道音軌。當Source是URL時,此信息僅在播放期間可用。僅當source是具有音頻(或軌道)的Video Clip,或者你的source是URL(允許你只是在播放期間從URL預期有多少軌道)時,才會顯示此屬性。
Audio source:指定播放的音軌,可以是Audio Clips。audio source的播放控件(Play On Awake以及Play())不支持video source's audio track;這個屬性只有Audio Output Mode設置為Audio Source時才會顯示。
Mute:將關聯的音軌靜音。在Audio Source模式下,使用audio source's的控制。這個屬性只有當Audio Output Mode設置為Direct時才會出現。
Volume:關聯的音軌的音量。在Audio Source模式下,使用audio source's的音量。這個屬性只有當Audio Output Mode設置為Direct時才會顯示
Video sources
Video Player組件可以播放從各種來源導入的內容
1.Video Clip
要創建和使用Video Clip Asset,你必須先導入視頻文件。將視頻文件拖放到Project window中會創建一個Video Clip
創建Video Clip的另一種方法是導航到Asset->Import New Asset以導入視頻文件。(如果視頻直接放到StreamingAssets中那么拖不到Video Clip中)
導入后,可以使用Select VideoClip窗口(可通過單擊Video Clip字段右側的圓圈選擇按鈕訪問)或通過將Video Clip Asset拖放到相應的Video Player組件字段來選擇新的Video Clip。
2.URLs
使用source的下拉菜單將video source設置為URL(默認情況下,此屬性設置為Video Clip).將Source設置為URL可以直接使用文件系統中的文件,可以帶或不帶file://前綴。URL source選項繞過了Asset管理,這意味着你必須手動確保Unity可以找到源視頻。例如,Web URL需要Web服務器來托管源視頻,而普通文件必須位於Unity可以找到它的地方,用腳本表示。如果內容不在Unity的直接控制之下,或者你希望避免在本地存儲大型視頻文件,則此功能非常有用。將Video Player組件Source設置為URL也可以通過http://和https://從web source讀取視頻。在這些情況下,Unity執行必要的預緩沖和錯誤管理。
3.Asset Bundle
Video Clips也可以從Asset Bundle讀取。導入后,可以通過將這些Video Clips分配給Video Clip組件的Video Clip字段來使用它們。
4.Streaming Assets
置於Unity StreamingAssets文件夾中的文件可以通過Video Player組件的URL選項(參見上文)使用,也可以使用特定平台的路徑(Application.streamingAssetsPath).
視頻文件的兼容性
Unity可以導入許多不同格式的視頻文件。導入后,視頻文件存儲為VideoClip asset。但是,這些兼容性因你使用的平台而異。請參閱下表以獲取完整兼容性列表。
Windows:.asf,.avi,.dv,.mv4,.mov,.mp4,.mpg,.mpeg,.ogv,.vp8,.webm,.wmv
OSX:.dv,.m4v,.mov,.mp4,.mpg,.mpeg,.ogv,.vp8,.webm,.wmv
Linux:.ogv,.vp8,.webm
這些格式中的每一種都可以包含具有許多不同[codecs]的軌道。每個平台的每個版本還支持不同的編解碼器列表,因此務必查閱正在使用的平台的官方文檔。例如:Windows和OSX都提供有關其各自編解碼器兼容性的官方文檔。有關這些平台的更多兼容性信息,可以參閱Windows和OSX的官方文檔。如果編輯器無法讀取文件中軌道的內容,則會生成錯誤信息。如果發生這種情況,你必須進行視頻轉換或重新進行編碼軌道,以便Editor平台的native libraries可以使用它。
H.264(通常采用.mp4,.m4v或.mov格式)是最佳支持的視頻編解碼器,因為它提供跨平台的最佳兼容性。通過取消選中Video Clip importer中的Transcode復選框,也可以在不進行轉碼的情況下使用Video Clips。這使你可以使用視頻文件而無需任何額外的轉換,這樣可以更快,並防止因重新編碼而導致質量損失。
注意:為了獲得最佳效果,請務必檢查每個目標平台是否支持你的視頻文件。
視頻透明度支持
Unity的Video Clip和Video Player組件支持alpha。這是用於指代透明度的標准術語。在圖形學術語中,alpha是另一種說透明度的方式。Alpha是一個連續值,而不是可以打開或關閉的值。最低的alpha值意味着圖像完全透明(根本不可見),而最高的alpha值意味着它完全不透明(圖像是實心的,無法透視)。中間值使圖像部分透明,允許你同時查看圖像和背后的背景。Video Player組件在Camera’s near或 far planes中播放其內容時支持全局Alpha值。視頻也可以具有每像素透明度值,這意味着視頻圖像的透明度可能會有所不同。每像素透明度控制在生成圖像和視頻的應用程序(如NUKE或After Effects)中完成,而不是在Unity編輯器中完成。
Unity支持兩種具有每像素透明度的視頻: