unity播放视频(进度条控制视频进度,包含进度条事件绑定)
一.进度条播放视频
相关代码
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支持两种具有每像素透明度的视频:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!