将视频内容播放到目标上。
内容可以是 VideoClip 导入资源,也可以是 URL(例如 file://
或 http://
)。视频内容将投射到一个受支持的目标上,例如摄像机背景或 RenderTexture。
如果视频内容包括透明度,此透明度将出现在目标中,允许视频目标后面的对象可见。当数据 VideoPlayer.source 设置为 URL 时,只有在 VideoPlayer 准备完成后才会初始化正在播放的内容的音频和视频描述。这可以通过 VideoPlayer.isPrepared 进行测试。
电影文件格式支持说明
VideoPlayer 使用原生音频和视频解码库。需要使用符合目标平台要求的视频。VideoClipImporter 提供了一个将 VideoClip 资源转码为 H.264、H.265 或 VP8 视频编解码器的选项,以及一些实验性选项(例如 Resolution)。这会将匹配的编解码器用于音频轨道:分别为 AAC 和 Vorbis。
另请参阅:VideoClipImporter.SetTargetSettings 和 VideoImporterTargetSettings.enableTranscoding。
您可以选择忽略此转码,而是改用已知受目标系统支持的视频,同时使用外部程序更精确地控制编码过程。在使用过程中,VideoClipImporter 编辑器会提供指导和警告,以更好地帮助您做出正确的格式和编码选择。
目前,必须遵循供应商建议,而且在旧版移动平台上尤其受到约束。例如,您在 Web 中找到的视频通常需要经过检查和相关操作,才能在运行在多个设备上的游戏环境中可靠地使用。以下是一些建议和已知限制的示例:
* Android:支持的媒体格式。请参阅下方的附加说明。
* Windows:支持的媒体格式,H.265
* iPhone 6-7:比较 iPhone 型号(请参阅“电视和视频”)
* UWP:支持的编解码器
可用于硬件加速的原生支持的最优视频编解码器是 H.264,同时 VP8 作为可以在需要时使用的软件解码解决方案。在 Android 上,VP8 还支持使用原生库,因此也可以根据型号对硬件进行辅助。在设备支持的情况下,H.265 也可用于硬件加速。要在编码参数中查找的键值:
* Video Codec:H.264、H.265 或 VP8。
* Resolution:例如:1280 x 720。
* Profile:适用于 H.264/H.265。配置文件是一组功能和约束;供应商通常会指定此配置文件,例如“Baseline”或“Main”。请参阅 H.264 或 H.265。
* Profile Level:适用于 H.264/H.265。在一个给定配置文件中,级别会指定某些性能要求,例如“Baseline 3.1”。请参阅 H.264 和 H.265
* Audio Codec:通常是 AAC(适用于使用 H.264/H.265 的 mp4 视频)或 Vorbis(适用于使用 VP8 的 webm 视频)。
* Audio Channels:取决于平台。例如,针对 Android 的建议是立体声文件,但很多设备都接受 5.1。
关于 Android 的注意事项
* 并非所有设备都支持高于 640 x 360 的分辨率。执行运行时检查来验证这一点,未遵循此要求将导致电影无法播放。
* 对于 Jelly Bean/MR1,由于操作系统库中存在错误,分辨率高于 1280 x 720 或拥有 2 个以上音频轨道的电影将无法播放。
* 对于 Lollipop 及以上版本,可以尝试播放任何分辨率或拥有任何数量音频轨道的电影,但会受到设备功能的限制。
* Unity 2019.1 及更高版本支持 Vulkan 图形 API。
* 格式兼容性问题将在 adb logcat
输出中报告,并始终以 AndroidVideoMedia
为前缀。
* 还需注意特定于设备的错误消息(位于 Unity 错误消息附近):它们对于引擎来说不可用,但通常会说明兼容性问题。
* 只有直接从磁盘读取的非压缩包支持从资源包中播放。
* 目标为 Android 9 或更高版本并通过 HTTP 播放时,必须将 usesCleartextTraffic 属性添加到 Android 清单中;或者,必须在网络安全配置文件中启用到特定域的明文通信。
H.265 兼容性说明
OSX
要求:SDK 10.13+
硬件解码:第六代 Intel Core 处理器
软件编码:所有 Mac 机型
硬件解码:第六代 Intel Core 处理器
软件解码:所有 Mac 机型
Windows
要求:Windows 10 + HEVC 扩展
HEVC 扩展(仅硬件)
HEVC 扩展(硬件 + 软件支持)
编码器
解码器
iOS
要求:SDK 11.0+
硬件解码:A9 芯片
软件解码:所有 iOS 设备
tvOS
要求:SDK 11.0+
XBox
要求:请参阅此处
UWP
要求:Windows 10 + 请参阅此处
注意:在表明支持 H.265 的情况下,不一定是设备系列中的所有设备都支持。
Android:
要求:5.0+请参阅此处
以下部分演示了 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 | 返回对象的名称。 |
Destroy | 移除 GameObject、组件或资源。 |
DestroyImmediate | 立即销毁对象 /obj/。强烈建议您改用 Destroy。 |
DontDestroyOnLoad | 在加载新的 Scene 时,请勿销毁 Object。 |
FindObjectOfType | 返回第一个类型为 type 的已加载的激活对象。 |
FindObjectsOfType | 返回所有类型为 type 的已加载的激活对象的列表。 |
Instantiate | 克隆 original 对象并返回克隆对象。 |
bool | 该对象是否存在? |
operator != | 比较两个对象是否引用不同的对象。 |
operator == | 比较两个对象引用,判断它们是否引用同一个对象。 |