将视频内容播放到目标上。
内容可以是 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 == | 比较两个对象引用,判断它们是否引用同一个对象。 |