将视频内容播放到目标上。
内容可以是 VideoClip 导入资源,也可以是 URL(例如 file://
或 http://
)。视频内容将投射到一个受支持的目标上,例如摄像机背景或 RenderTexture。
如果视频内容包括透明度,此透明度将出现在目标中,允许视频目标后面的对象可见。当数据 VideoPlayer.source 设置为 URL 时,只有在 VideoPlayer 准备完成后才会初始化正在播放的内容的音频和视频描述。这可以通过 VideoPlayer.isPrepared 进行测试。
**电影文件格式支持说明**
VideoPlayer 在其实现中使用原生音频和视频解码库,您有责任使用符合目标平台要求的视频。VideoClipImporter 提供了一个将 VideoClip 资源转码为 H.264 或 VP8 视频编解码器的选项,以及一些实验性选项(例如 Resolution)。这会将匹配的编解码器用于音频轨道:分别是 AAC 和 Vorbis。
另请参阅:VideoClipImporter.SetTargetSettings 和 VideoImporterTargetSettings.enableTranscoding。
您可以选择忽略此转码,而是改用已知受目标系统支持的视频,同时使用外部程序更精确地控制编码过程。在使用过程中,VideoClipImporter 编辑器会提供指导和警告,以更好地帮助您做出正确的格式和编码选择。
目前,必须遵循供应商建议,而且在旧版移动平台上尤其受到约束。例如,您在 Web 中找到的视频通常需要经过检查和相关操作,才能在运行在多个设备上的游戏环境中可靠地使用。以下是一些建议和已知限制的示例:
***** Android:支持的媒体格式:。请参阅下方的附加说明。\
***** Windows:H.264 视频解码器(请参阅“格式约束”)\
***** iPhone 6-7:比较 iPhone 型号(请参阅“电视和视频”)
可用于硬件加速的本机支持的最优视频编解码器是 H.264,同时 VP8 作为可以在需要时使用的软件解码解决方案。在 Android 上,VP8 还支持使用本机库,因此也可以根据型号对硬件进行辅助。要在编码参数中查找的键值:
***** Video Codec:H.264 或 VP8。\
***** Resolution:例如:1280 x 720。\
***** Profile:适用于 H.264。配置文件是一组功能和约束;供应商通常会指定此配置文件,例如“Baseline”或“Main”。请参阅here.\
***** Profile Level:适用于 H.264。在一个给定配置文件中,级别会指定某些性能要求,例如“Baseline 3.1”。请参阅here.\
***** Audio Codec:通常是 AAC(适用于使用 H.264 的 mp4 视频)或 Vorbis(适用于使用 VP8 的 webm 视频)。\
***** Audio Channels:取决于平台。例如,针对 Android 的建议是立体声文件,但很多设备都接受 5.1。
**关于 Android 的注意事项**
***** 并非所有设备都支持高于 640 x 360 的分辨率。执行运行时检查来验证这一点,未遵循此要求将导致电影无法播放。\
***** 对于 Jelly Bean/MR1,由于操作系统库中存在错误,分辨率高于 1280 x 720 或拥有 2 个以上音频轨道的电影将无法播放。\
***** 对于 Lollipop 及以上版本,可以尝试播放任何分辨率或拥有任何数量音频轨道的电影,但会受到设备功能的限制。\
***** 目前尚不支持 Vulkan 图形 API。\
***** 格式兼容性问题将在 adb logcat
输出中报告,并始终以 AndroidVideoMedia
为前缀。\
***** 还需注意特定于设备的错误消息(位于 Unity 错误消息附近):它们对于引擎来说不可用,但通常会说明兼容性问题。\
***** 只有直接从磁盘读取的非压缩包支持从资源包中播放。
**以下部分演示了 VideoPlayer 的一些功能:**
// Examples of VideoPlayer function
using UnityEngine;
public class Example : MonoBehaviour { void Start() { // Will attach a VideoPlayer to the main camera. GameObject camera = GameObject.Find("Main Camera");
// VideoPlayer automatically targets the camera backplane when it is added // to a camera object, no need to change videoPlayer.targetCamera. var videoPlayer = camera.AddComponent<UnityEngine.Video.VideoPlayer>();
// Play on awake defaults to true. Set it to false to avoid the url set // below to auto-start playback since we're in Start(). videoPlayer.playOnAwake = false;
// By default, VideoPlayers added to a camera will use the far plane. // Let's target the near plane instead. videoPlayer.renderMode = UnityEngine.Video.VideoRenderMode.CameraNearPlane;
// This will cause our Scene to be visible through the video being played. videoPlayer.targetCameraAlpha = 0.5F;
// Set the video to play. URL supports local absolute or relative paths. // Here, using absolute. videoPlayer.url = "/Users/graham/movie.mov";
// Skip the first 100 frames. videoPlayer.frame = 100;
// Restart from beginning when done. videoPlayer.isLooping = true;
// Each time we reach the end, we slow down the playback by a factor of 10. videoPlayer.loopPointReached += EndReached;
// Start playback. This means the VideoPlayer may have to prepare (reserve // resources, pre-load a few frames, etc.). To better control the delays // associated with this preparation one can use videoPlayer.Prepare() along with // its prepareCompleted event. videoPlayer.Play(); }
void EndReached(UnityEngine.Video.VideoPlayer vp) { vp.playbackSpeed = vp.playbackSpeed / 10.0F; } }
**MovieTexture 迁移注意事项**
由于 VideoPlayer 与传统电影播放解决方案 MovieTexture 存在根本的不同,我们提供了一些示例来帮助您使用 MovieTexture 将项目迁移到新的 VideoPlayer 解决方案。
**播放电影示例**:
MovieTexture:
using UnityEngine;
public class PlayMovieMT : MonoBehaviour { public AudioClip movieAudioClip; public MovieTexture movieTexture;
void Start() { var audioSource = gameObject.AddComponent<AudioSource>(); audioSource.clip = movieAudioClip; }
void Update() { if (Input.GetButtonDown("Jump")) { var audioSource = GetComponent<AudioSource>(); GetComponent<Renderer>().material.mainTexture = movieTexture;
if (movieTexture.isPlaying) { movieTexture.Pause(); audioSource.Pause(); } else { movieTexture.Play(); audioSource.Play(); } } } }
VideoPlayer:
using UnityEngine;
public class PlayMovieVP : MonoBehaviour { public UnityEngine.Video.VideoClip videoClip;
void Start() { var videoPlayer = gameObject.AddComponent<UnityEngine.Video.VideoPlayer>(); var audioSource = gameObject.AddComponent<AudioSource>();
videoPlayer.playOnAwake = false; videoPlayer.clip = videoClip; videoPlayer.renderMode = UnityEngine.Video.VideoRenderMode.MaterialOverride; videoPlayer.targetMaterialRenderer = GetComponent<Renderer>(); videoPlayer.targetMaterialProperty = "_MainTex"; videoPlayer.audioOutputMode = UnityEngine.Video.VideoAudioOutputMode.AudioSource; videoPlayer.SetTargetAudioSource(0, audioSource); }
void Update() { if (Input.GetButtonDown("Jump")) { var vp = GetComponent<UnityEngine.Video.VideoPlayer>();
if (vp.isPlaying) { vp.Pause(); } else { vp.Play(); } } } }
**下载电影示例**:
MovieTexture:
using UnityEngine;
public class DownloadMovieMT : MonoBehaviour { void Start() { StartCoroutine(GetMovieTexture()); }
IEnumerator GetMovieTexture() { using (var uwr = UnityWebRequestMultimedia.GetMovieTexture("http://myserver.com/mymovie.ogv")) { yield return uwr.SendWebRequest(); if (uwr.isNetworkError || uwr.isHttpError) { Debug.LogError(uwr.error); yield break; }
MovieTexture movie = DownloadHandlerMovieTexture.GetContent(uwr);
GetComponent<Renderer>().material.mainTexture = movie; movie.loop = true; movie.Play(); } } }
VideoPlayer:
using UnityEngine;
public class DownloadMovieVP : MonoBehaviour { void Start() { var vp = gameObject.AddComponent<UnityEngine.Video.VideoPlayer>(); vp.url = "http://myserver.com/mymovie.mp4";
vp.isLooping = true; vp.renderMode = UnityEngine.Video.VideoRenderMode.MaterialOverride; vp.targetMaterialRenderer = GetComponent<Renderer>(); vp.targetMaterialProperty = "_MainTex";
vp.Play(); } }
controlledAudioTrackMaxCount | 可以控制的最大音频轨道数量。(只读) |
aspectRatio | 定义如何拉伸视频内容以填充目标区域。 |
audioOutputMode | 嵌入在视频中的音频的目标。 |
audioTrackCount | 在当前配置的数据源中找到的音频轨道数量。(只读) |
canSetDirectAudioVolume | 当前平台和视频格式是否支持直接输出音量控制。(只读) |
canSetPlaybackSpeed | 播放速度是否可以更改。(只读) |
canSetSkipOnDrop | 是否可以控制跳帧以保持同步。(只读) |
canSetTime | 是否可以使用 time 或 timeFrames 属性更改当前时间。(只读) |
canSetTimeSource | 是否可以更改 VideoPlayer 遵循的时间源。(只读) |
canStep | 如果 VideoPlayer 可以使视频内容前进,则返回 /true/。(只读) |
clip | VideoPlayer 正在播放的剪辑。 |
clockTime | VideoPlayer 采样时遵循的时钟时间。此时钟时间以秒为单位。(只读) |
controlledAudioTrackCount | 此 VideoPlayer 将控制的音频轨道数量。 |
externalReferenceTime | VideoPlayer 用于纠正其偏差的外部时钟的参考时间。 |
frame | VideoPlayer.texture 中当前可用帧的帧索引。 |
frameCount | 当前视频内容中的帧数。(只读) |
frameRate | 剪辑或 URL 的帧率(以帧/秒为单位)。(只读) |
height | VideoClip 或 URL 中的图像的高度(以像素为单位)。(只读) |
isLooping | 确定当 VideoPlayer 到达剪辑的结尾时是否从头开始播放。 |
isPaused | 是否已暂停播放。(只读) |
isPlaying | 是否正在播放内容。(只读) |
isPrepared | VideoPlayer 是否已完成待播放内容的准备工作。(只读) |
length | VideoClip 或 URL 的长度(以秒为单位)。(只读) |
pixelAspectRatioDenominator | VideoClip 或 URL 的像素宽高比(分子:分母)的分母。(只读) |
pixelAspectRatioNumerator | VideoClip 或 URL 的像素宽高比(分子:分母)的分子。(只读) |
playbackSpeed | 基本播放速率的增加倍数。 |
playOnAwake | 内容是否会在组件被唤醒后立即开始播放。 |
renderMode | 将绘制视频内容的位置。 |
sendFrameReadyEvents | 启用 frameReady 事件。 |
skipOnDrop | 是否允许 VideoPlayer 跳帧以追上当前时间。 |
source | VideoPlayer 用于播放的源。 |
targetCamera | 当 VideoPlayer.renderMode 设置为 VideoRenderMode.CameraFarPlane 或 VideoRenderMode.CameraNearPlane 时,要在其中绘制资源的 Camera 组件。 |
targetCamera3DLayout | 源视频媒体中包含的 3D 内容的类型。 |
targetCameraAlpha | 目标摄像机平面视频的整体透明度级别。 |
targetMaterialProperty | 在 VideoPlayer.renderMode 设置为 Video.VideoTarget.MaterialOverride 时被设为目标的 Material 纹理属性。 |
targetMaterialRenderer | 在 VideoPlayer.renderMode 设置为 Video.VideoTarget.MaterialOverride 时被设为目标的 Renderer |
targetTexture | 当 VideoPlayer.renderMode 设置为 Video.VideoTarget.RenderTexture 时,要在其中绘制资源的 RenderTexture。 |
texture | 放置视频内容的内部纹理。(只读) |
time | VideoPlayer.texture 中当前可用帧的准备时间。 |
timeReference | VideoPlayer 对其进行观测以发现和纠正偏差的时钟。 |
timeSource | [尚未实现] VideoPlayer 用于派生其当前时间的源。 |
url | VideoPlayer 将从中读取内容的文件或 HTTP URL。 |
waitForFirstFrame | 确定当 VideoPlayer.playOnAwake 启用时,VideoPlayer 是否会在开始播放之前等待第一帧加载到纹理中。 |
width | VideoClip 或 URL 中的图像的宽度(以像素为单位)。(只读) |
EnableAudioTrack | 启用/禁用音频轨道解码。仅在 VideoPlayer 当前未播放时有效。 |
GetAudioChannelCount | 指定音频轨道中的音频声道数。 |
GetAudioLanguageCode | 返回指定轨道的语言代码(如果有)。 |
GetAudioSampleRate | 获取音频轨道的采样率(以赫兹为单位)。 |
GetDirectAudioMute | 获取指定轨道的直接输出音频静音状态。 |
GetDirectAudioVolume | 返回指定轨道的直接输出音量。 |
GetTargetAudioSource | 获取当 VideoPlayer.audioOutputMode 设置为 VideoAudioOutputMode.AudioSource 时将接收指定轨道的音频样本的 AudioSource。 |
IsAudioTrackEnabled | 是否启用了对指定音频轨道的解码。请参阅 VideoPlayer.EnableAudioTrack 以了解它与静音的区别。 |
Pause | 暂停播放并保持当前时间不变。 |
Play | 开始播放。 |
Prepare | 启动播放引擎准备。 |
SetDirectAudioMute | 设置指定轨道的直接输出音频静音状态。 |
SetDirectAudioVolume | 设置指定轨道的直接输出音频音量。 |
SetTargetAudioSource | 设置当使用 VideoPlayer.audioOutputMode 选择此音频目标时将接收指定轨道的音频样本的 AudioSource。 |
StepForward | 立即将当前时间向前推进一帧。 |
Stop | 停止播放并将当前时间设为 0。 |
clockResyncOccurred | 在 VideoPlayer 时钟同步回其 VideoTimeReference 时调用。 |
errorReceived | 通过此回调报告 HTTP 连接问题等错误。 |
frameDropped | [尚未实现] 当视频解码器在播放期间没有按照时间源生成帧时调用。 |
frameReady | 当新帧准备就绪时调用。 |
loopPointReached | 当 VideoPlayer 到达播放内容的结尾时调用。 |
prepareCompleted | 当 VideoPlayer 的准备工作完成后调用。 |
seekCompleted | 在搜寻操作完成后调用。 |
started | 在调用 Play 后立即调用。 |
ErrorEventHandler | 包含错误消息的 VideoPlayer 事件的委托类型。 |
EventHandler | VideoPlayer 发出的所有无参数事件的委托类型。 |
FrameReadyEventHandler | 带有帧编号的 VideoPlayer 事件的委托类型。 |
TimeEventHandler | 带有时间位置的 VideoPlayer 事件的委托类型。 |
enabled | 启用的 Behaviour 可更新,禁用的 Behaviour 不可更新。 |
isActiveAndEnabled | 是否已激活并启用 Behaviour? |
gameObject | 此组件附加到的游戏对象。始终将组件附加到游戏对象。 |
tag | 此游戏对象的标签。 |
transform | 附加到此 GameObject 的 Transform。 |
hideFlags | 该对象应该隐藏、随场景一起保存还是由用户修改? |
name | 对象的名称。 |
BroadcastMessage | 调用此游戏对象或其任何子项中的每个 MonoBehaviour 上名为 methodName 的方法。 |
CompareTag | 此游戏对象是否使用 tag 进行了标记? |
GetComponent | 如果游戏对象附加了类型为 type 的组件,则将其返回,否则返回 null。 |
GetComponentInChildren | 使用深度首次搜索返回 GameObject 或其任何子项中类型为 type 的组件。 |
GetComponentInParent | 返回 GameObject 或其任何父项中类型为 type 的组件。 |
GetComponents | 返回 GameObject 中类型为 type 的所有组件。 |
GetComponentsInChildren | 返回 GameObject 或其任何子项中类型为 type 的所有组件。 |
GetComponentsInParent | 返回 GameObject 或其任何父项中类型为 type 的所有组件。 |
SendMessage | 调用此游戏对象中的每个 MonoBehaviour 上名为 methodName 的方法。 |
SendMessageUpwards | 调用此游戏对象中的每个 MonoBehaviour 上或此行为的每个父级上名为 methodName 的方法。 |
GetInstanceID | 返回对象的实例 ID。 |
ToString | 返回 GameObject 的名称。 |
Destroy | 删除 GameObject、组件或资源。 |
DestroyImmediate | 立即销毁对象 /obj/。强烈建议您改用 Destroy。 |
DontDestroyOnLoad | 在加载新的 Scene 时,请勿销毁 Object。 |
FindObjectOfType | 返回第一个类型为 type 的已加载的激活对象。 |
FindObjectsOfType | 返回所有类型为 type 的已加载的激活对象的列表。 |
Instantiate | 克隆 original 对象并返回克隆对象。 |
bool | 该对象是否存在? |
operator != | 比较两个对象是否引用不同的对象。 |
operator == | 比较两个对象引用,判断它们是否引用同一个对象。 |
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.