Unity3d 基于UGUI和VideoPlayer 实现一个多功能视频播放器功能(含源码)

前言

随着Unity3d引擎在数字沙盘、智慧工厂、数字孪生等场景的广泛应用,视频已成为系统程序中展示时,不可或缺的一部分。在 Unity3d 中,我们可以通过强大的 VideoPlayer 组件和灵活的 UGUI 系统,将视频播放功能无缝集成到用户界面中,从而提升应用的用户体验。作为展示内容的媒体播放器,视频播放功能都需要一个清晰、易于交互的界面,所以本文就是以 VideoPlayer 组件为播放功能,通过UGUI搭建配套的操作界面,实现一个视频播放器功能。其功能包括:VideoClip播放、选择文件播放、播放/暂停、进度拖拽、快进/快退、速度调节、音量条件和视频画面尺寸自适应。
关注并私信 U3D视频播放器 免费获取源码(底部公众号)。

效果

选择文件播放:
在这里插入图片描述

快进:
在这里插入图片描述

进度拖拽:
在这里插入图片描述

横屏自动适配:
在这里插入图片描述

实现

实现关键组件包括:
1.VideoPlayer 组件:
VideoPlayer 是 Unity 中用于播放视频文件的核心组件。它能够播放本地视频文件或者通过网络流播放视频,并支持控制视频播放的各项参数,如播放、暂停、停止、音量控制、视频进度等。

2.RawImage 组件:
为了在 UI 中显示视频内容,我们可以使用 RawImage 组件。RawImage 是 Unity UGUI 中的一种 UI 组件,能够显示纹理,可以将视频流(VideoPlayer 播放的视频)输出到 RawImage 上进行显示。

3.Button、Slider 和 Text 组件:
为了实现播放、暂停、音量控制等功能,UGUI 提供了按钮(Button)、滑块(Slider)和文本(Text)组件,允许用户通过界面直接与视频进行交互。

按照步骤将实现过程拆分为UI搭建和编码实现。

UI搭建

播放器UI搭建的效果如下图:
在这里插入图片描述

使用 Button 控件来创建播放/暂停、快进快退按钮;使用 Slider 控件创建音量滑块、速度滑块和播放进度条实时更新视频的播放进度。使用 RawImage 控件显示视频内容,VideoPlayer 的视频输出会被设置为 RawImage.texture,从而将视频渲染到 UI 上。

编码

视频播放器的UI搭建好后,绑定对应的事件:

 #region 事件处理//点击暂停public void ClickPause(){LastInTime = Time.time;videoPlayer.Pause();PlayBtn.SetActive(true);PauseBtn.SetActive(false);CenterPlayBtn?.SetActive(true);ShowTip("暂停");}//点击播放 public void ClickPlay(){CenterPlayBtn?.SetActive(false);videoPlayer.Play();PlayBtn.SetActive(false);PauseBtn.SetActive(true);if (isIn){isIn = false;CtrlTran.DOAnchorPos3D(OutPos, ScaleDura * 2);}ShowTip("播放");}//快进public void ClickForward() {double nowPos = videoPlayer.time + SpeedStep;videoPlayer.time = nowPos > VideoLength ? VideoLength : nowPos;LastInTime = Time.time;ShowTip("快进");}//快退public void ClickBackward() {double nowPos = videoPlayer.time - SpeedStep;videoPlayer.time = nowPos < 0 ? 0 : nowPos;LastInTime = Time.time;ShowTip("快退");}public void MouseInCtrls(){LastInTime = Time.time;isOverCtrls = true;}public void MouseOutCtrls(){LastInTime = Time.time;isOverCtrls = false;}//音量滑动条变更public void OnVolumeChanged(){LastInTime = Time.time;// Set new audio output volumevideoPlayer.SetDirectAudioVolume(0, VolSlider.value); // * 100ShowTip("播放音量:"+ (VolSlider.value * 100).ToString("F0"));}//进度滑动条变更public void OnTimeChanged(float val){LastInTime = Time.time;videoPlayer.time = val * VideoLength;TimeSlider.value = val;ShowTip("播放时间:" + videoPlayer.time.ToString("F0"));}//速度重置public void ClickSpeed(){SpeedSlider.value = 0.2f;videoPlayer.playbackSpeed = 1;SpeedText.text = "速度×1.0";ShowTip("播放速度" + videoPlayer.playbackSpeed);}//速度滑动条拖拽public void OnSpeedChange(float val){float speed = val / 0.2f;videoPlayer.playbackSpeed = speed;SpeedText.text = "速度×" + speed.ToString("F1");ShowTip("播放" + SpeedText.text);}#endregion 事件处理

完整代码如上,音量滑块(Slider 控件),通过 videoPlayer.SetDirectAudioVolume() 方法来调整音量;播放速度滑块(Slider 控件),通过videoPlayer.playbackSpeed 属性来调整播放速度;进度条(Slider 控件),实时更新视频的播放进度,并通过 videoPlayer.time 属性控制视频的当前播放时间;播放/暂停按钮(Button 控件),监听其点击事件,并通过 VideoPlayer 的 Play() 和 Pause() 方法控制视频的播放和暂停。其中TipText是提示的Text控件,状态变更时候会进行文字提示。

视频的控制按钮面板,对其进行了默认移出播放画面,鼠标点击移入,无操作一段时间后移出画面的处理。

视频画面高宽自适应:

Canvas canvas = transform.GetComponentInParent<Canvas>();
float WidRate = videoPlayer.width / (float)Screen.width;//Screen.width;
float HeightRate = videoPlayer.height / (float)Screen.height;//Screen.height;//Debug.Log("VideoRt.sizeDelta:" + VideoRt.sizeDelta);
if (WidRate >= HeightRate)   //适配宽度
{float Width = (float)Screen.width / canvas.transform.localScale.x;float Height = (Screen.width / (float)videoPlayer.width) * videoPlayer.height / canvas.transform.localScale.y;VideoRt.sizeDelta = new Vector2(Width, Height);//Debug.Log("适配宽度  width:" + Width + "  height:" + Height);
}
else  //适配高度
{float Width = Screen.height / (float)videoPlayer.height * videoPlayer.width / canvas.transform.localScale.x;float Height = (float)Screen.height / canvas.transform.localScale.y;VideoRt.sizeDelta = new Vector2(Width, Height);//Debug.Log("适配高度 width:" + Width + "  height:" + Height);
}// 先释放当前的 RenderTexture 资源
if (renderTexture != null)
{renderTexture.Release();// 设置新的宽高renderTexture.width = (int)videoPlayer.width;renderTexture.height = (int)videoPlayer.height;
}
elserenderTexture = new RenderTexture((int)videoPlayer.width, (int)videoPlayer.height, 24);renderTexture.Create();videoPlayer.targetTexture = renderTexture;fullImg.texture = renderTexture;

尺寸的适应采用高宽比的思路,如果宽度比 比 高度比高就适配宽度,反之则适配高度(这里比较拗口,详情参看代码)。因为renderTexture的尺寸需要动态变更,所以这里都是先进行释放了,然后再进行创建。

在播放过程中显示00:00:00/00:00:00的时间格式,设置函数如下:

//设置已播时长
void SetPlayerTime() //long playedTime
{TimeSpan time = TimeSpan.FromSeconds(videoPlayer.time);//TimeSpan.FromMilliseconds(playedTime);NowTimeText.text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);if (isIn){TimeSlider.value = VideoLength > 0 ? (float)(videoPlayer.time / VideoLength) : 0;}
}//设置视频时长
void SetMediaLength(long mediaLength)
{VideoLength = mediaLength;//Debug.Log("SetMediaLength:" + mediaLength);var length = TimeSpan.FromSeconds(mediaLength);//TimeSpan.FromMilliseconds(mediaLength);AllTimeText.text = string.Format("{0:D2}:{1:D2}:{2:D2}", length.Hours, length.Minutes, length.Seconds);
}

使用方法

1.加入工程后将“VideoPlayer.prefab” 预设加入场景。

2.可以通过调用的接口的方式启动播放器:
传入VideoClip:

public void PlayClip(VideoClip clip, Transform tran = null)

clip是视频片段。

通过传入地址:

public void PlayVideoByUrl(string url, Transform tran = null)

url是地址。

tran 是动画的起始位置对象,可不传。传入后可以有触发位置移动到屏幕中间的动画效果:
在这里插入图片描述

案例中直接打开VideoClip的调用:

public VideoClip vc;
//直接播放片段
public void ClickPlayClip(GameObject sender) {VideoPlayerCtrl.instance?.PlayClip(vc, sender.transform);
}

案例中的选择视频的调用:

//打开视频文件
public void ClickChooseBtn(GameObject sender)
{OpenFileName file = new OpenFileName();file.structSize = Marshal.SizeOf(file);file.filter = "文件(*.MP4;*.mp4;*.Mp4;*.wmv;*.rm;*.rmvb;*.avi;*.mkv;*.flv)\0*.mp4;*.mp4;*.Mp4;*.wmv;*.rm;*.rmvb;*.avi;*.mkv;*.flv";file.file = new string(new char[256]);file.maxFile = file.file.Length;file.fileTitle = new string(new char[64]);file.maxFileTitle = file.fileTitle.Length;file.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径file.title = "选择文件";file.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;if (SelectFileDialog.GetSaveFileName(file)){VideoPlayerCtrl.instance?.PlayVideoByUrl(file.file, sender.transform);}}

这里使用了comdlg32.dll,comdlg32.dll是Windows操作系统中的一个动态链接库(DLL)文件,主要用于提供多种标准对话框的实现功能。这些对话框包括文件打开/保存对话框、颜色选择器等,对于本视频播放器来说主要就是选择视频文件并打开播放。

Unity3d中的Comdlg32.dll引用:

using System.Runtime.InteropServices;public class SelectFileDialog
{//系统函数  [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);public static bool GetSFN([In, Out] OpenFileName ofn){return GetSaveFileName(ofn);}
}

源码

https://download.csdn.net/download/qq_33789001/90178128

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

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

相关文章

第22天:信息收集-Web应用各语言框架安全组件联动系统数据特征人工分析识别项目

#知识点 1、信息收集-Web应用-开发框架-识别安全 2、信息收集-Web应用-安全组件-特征分析 一、ICO图标&#xff1a; 1、某个应用系统的标示&#xff0c;如若依系统有自己特点的图标&#xff1b;一旦该系统出问题&#xff0c;使用该系统的网站都会受到影响&#xff1b; 2、某个公…

我的 2024 年终总结

2024 年&#xff0c;我离开了待了两年的互联网公司&#xff0c;来到了一家聚焦教育机器人和激光切割机的公司&#xff0c;没错&#xff0c;是一家硬件公司&#xff0c;从未接触过的领域&#xff0c;但这还不是我今年最重要的里程碑事件 5 月份的时候&#xff0c;正式提出了离职…

acme ssl证书自动续签 nginx

参考 github 官方操作 &#xff0c;acme操作说明 说下我的操作 安装 acme.sh curl https://get.acme.sh | sh source ~/.bashrc 2.注册 acme.sh --register-account -m 123qq.com 如果你在配置 acme.sh 时选择了其他 CA&#xff08;如 Let’s Encrypt&#xff09;&#xff…

sentinel学习笔记6-限流降级(上)

本文属于sentinel学习笔记系列。网上看到吴就业老师的专栏&#xff0c;写的好值得推荐&#xff0c;我整理的有所删减&#xff0c;推荐看原文。 https://blog.csdn.net/baidu_28523317/category_10400605.html sentinel 实现限流降级、熔断降级、黑白名单限流降级、系统自适应…

简单了解函数递归

函数递归 一 了解函数递归二 深入理解函数递归的思想三 函数递归的优缺点 一 了解函数递归 首先&#xff0c;我们通过一个简单的代码来理解函数递归。 #include<stdio.h> int Func() {return Func(n1); } int main() {int n 5;Func(n);return 0; }这个就是函数递归&am…

QT的前景与互联网岗位发展

qt是用来干什么的 --》桌面应用开发&#xff08;做电脑的应用程序&#xff0c;面对客户端&#xff09;。 主要用于开发跨平台的应用程序和用户界面&#xff08;UI&#xff09;。它是一个全面的C库集合&#xff0c;提供了构建软件应用所需的各种工具和功能。 客户端开发的重…

重温设计模式--2、设计模式七大原则

文章目录 1、开闭原则&#xff08;Open - Closed Principle&#xff0c;OCP&#xff09;定义&#xff1a;示例&#xff1a;好处&#xff1a; 2、里氏替换原则&#xff08;Liskov Substitution Principle&#xff0c;LSP&#xff09;定义&#xff1a;示例&#xff1a;好处&#…

第十五章 C++ 数组

C 支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量&#xff0c;比如 number0、number1、...、number99&#xff0c;而是声…

企业数字化转型加速,现代 IT 如何用 Datadog 全面提升可观测性?

作为 Gartner 可观测平台魔力象限的领导者&#xff0c;Datadog 凭借全面的功能、直观的用户界面和强大的产品路线图赢得了全球企业的信任。 企业 IT 架构正变得日益复杂&#xff0c;从本地服务器到云端部署&#xff0c;从单体应用向微服务&#xff0c;还有容器、 Kubernetes 等…

渗透Vulnhub-DC-9靶机

本篇文章旨在为网络安全渗透测试行业靶机教学。通过阅读本文&#xff0c;读者将能够对渗透Vulnhub系列DC-6靶机有定的了解 一、信息收集阶段 DC-9靶场信息: DC-9靶场介绍&#xff1a; https://www.vulnhub.com/entry/dc-9,412/ DC-9靶场下载&#xff1a; https://download.vu…

[WASAPI]从Qt MultipleMedia来看WASAPI

[WASAPI] 从Qt MultipleMedia 来看WASAPI 最近在学习有关Windows上的音频驱动相关的知识&#xff0c;在正式开始说WASAPI之前&#xff0c;我想先说一说Qt的Multiple Media&#xff0c;为什么呢&#xff1f;因为Qt的MultipleMedia实际上是WASAPI的一层封装&#xff0c;它在是线…

Linux下编译安装Kokkos

本文记录在Linux下编译安装Kokkos的流程。 零、环境 操作系统Ubuntu 22.04.4 LTSVS Code1.92.1Git2.34.1GCC11.4.0CMake3.22.1oneAPI2024.2.1 一、安装依赖 二、编译安装 参考文献 Mills R T. PETSc/TAO Developments for Early Exascale Systems[J]. 2024.Josef R. A Stud…

HTMLCSS:惊!3D 折叠按钮

这段代码创建了一个具有 3D 效果和动画的按钮&#xff0c;按钮上有 SVG 图标和文本。按钮在鼠标悬停时会显示一个漂浮点动画&#xff0c;图标会消失并显示一个线条动画。这种效果适用于吸引用户注意并提供视觉反馈。按钮的折叠效果和背景渐变增加了页面的美观性。 演示效果 HT…

容器技术所涉及Linux内核关键技术

容器技术所涉及Linux内核关键技术 一、容器技术前世今生 1.1 1979年 — chroot 容器技术的概念可以追溯到1979年的UNIX chroot。它是一套“UNIX操作系统”系统&#xff0c;旨在将其root目录及其它子目录变更至文件系统内的新位置&#xff0c;且只接受特定进程的访问。这项功…

Git远程仓库的多人协作

目录 一.项目克隆 二.多人协作 1.创建林冲仓库 2.协作处理 3.处理冲突 三.分支推送协作 四.分支拉取协作 五.远程分支的删除 一.项目克隆 我们可以把远程项目克隆到本地形成一个本地的仓库 git clone https://github.com/txjava-teach/txjava-code.git //链接你自己的远…

Docker 部署 plumelog 最新版本 实现日志采集

1.配置plumelog.yml version: 3 services:plumelog:#此镜像是基于plumelog-3.5.3版本image: registry.cn-hangzhou.aliyuncs.com/k8s-xiyan/plumelog:3.5.3container_name: plumelogports:- "8891:8891"environment:plumelog.model: redisplumelog.queue.redis.redi…

Spring常见面试题总结

关于详细介绍&#xff0c;可以看我写的 ( Spring知识点) 这篇文章。 Spring 基础 什么是 Spring 框架? Spring 是一款开源的轻量级 Java 开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。 我们一般说 Spring 框架指的都是 Spring Framework&#xff0c…

Mac系统下 IDEA配置Maven本地仓库

1.为什么需要配置本地仓库&#xff1f; 在软件开发过程中&#xff0c;使用Maven工具进行依赖管理是常见的做法。Maven通过集中管理各种依赖库&#xff0c;能够帮助开发者在项目中轻松地引入所需的第三方库&#xff0c;并确保项目能够顺利构建和部署。然而&#xff0c;在使用Mav…

RGCL:A Review-aware Graph Contrastive Learning Framework for Recommendation

A Review-aware Graph Contrastive Learning Framework for Recommendation 解决的问题 基于评论的推荐可以自然地形成为具有来自相应用户项目评论的边特征的用户项目二分图。那么就可以利用评论感知图中独特的自监督信号来指导推荐的两个组件:用户-项目嵌入学习,用户-项目…

5、mysql的读写分离

主从复制 主从复制的含义 主从复制&#xff1a;在一个mysql的集群当中&#xff0c;至少3台&#xff0c;即主1台&#xff0c;从2台。 当有数据写入时&#xff0c;主负责写入本库&#xff0c;然后把数据同步到从服务器。 一定是在主服务器写入数据&#xff0c;从服务器的写入…