ARFoundation之路-视频播放

版权声明:Davidwang原创文章,严禁用于任何商业途径,授权后方可转载。

  在AR中播放视频也是一种常见的需求,如在一个展厅中放置的虚拟电视上播放宣传视频,或者在游戏中为营造氛围而设置的虚拟电视视频,本节我们将学习如何在AR场景中播放视频。

(一)VideoPlayer组件

  VideoPlayer是Unity一个跨平台播放视频的组件,这个组件在播放视频时会调用运行时系统本地的视频解码器,即其本身并不负责视频的解码,因此开发人员需要确保在特定平台上视频编码格式能被支持。VideoPlayer不仅能播放本地视频,也能够通过http协议播放远端服务器视频,而且支持将视频播放到摄像头平面(Camera Plane,包括近平面和远平面)、作为渲染纹理(Render Texture)、作为材质的纹理、其他组件的Texture属性,因此,可以方便的将视频播放到摄像头平面、3D物体上、UI界面等,功能非常之强大。VideoPlayer组件界面如下图所示:
在这里插入图片描述
  VideoPlayer组件主要属性意义如下表所示:

属性描述
Source视频源,其下拉菜单包括两个选项:Video Clip与URL。选择Video Clip时,可以将项目内的视频直接赋给Video Clip属性。当选择URL时,可以使用视频的路径定位视频(如使用http://或者file://),我们既可以在编译前为其设置固定的地址信息,也可以在运行时通过脚本代码实时的修改这个路径达到动态控制视频加载的目的。
Play On Awake是否在场景加载后就播放视频,如果不勾选该项,应当在运行时通过脚本来播放视频。
Wait For First Frame该选项主要用来同步视频播放与场景进度,特别是在游戏场景中,如果勾选,Unity则会在游戏开始前等待源视频加载显示,如果取消勾选,则可能会丢弃前几帧以使视频以使视频播放与游戏的其余部分保持同步。在AR中建议不勾选,不勾选时视频会跳帧。
Loop循环播放。
Skip On Drop是否允许跳帧以保持与场景同步,建议勾选。
Playback Speed视频播放速度倍率,如设置为2,视频则以2倍速播放,范围为[0,10]。
Render Mode定义视频的渲染方式。其下拉菜单中包括四个选项:Camera Far Plane、Camera Near Plane、Render Texture、Material Override、API Only。各渲染方式功能如下:1、Camera Far Plane:将视频渲染到摄像机的远平面,其Alpha值可设置视频的透明度。2、Camera Near Plane:将视频渲染到摄像机的近平面,其Alpha值可设置视频的透明度。3、Render Texture:将视频渲染为Render Texture,通过设置Target Texture定义Render Texture组件渲染到其图像的Render Texture。4、Material Override:将视频渲染到物体材质上。5、API Only:不能使用脚本代码将视频渲染到VideoPlayer.texture属性中。
Audio Output Mode定义音轨输出,其下拉菜单包括四个选项:None、Audio Source、Direct、API only。选择None时不播放音轨;选择Audio Source时可以自定义音频输出;选择Direct时,会直接将视频中的音轨输出;选择API only时,只能使用脚本代码控制音轨的设置。
Mute是否禁音。
Volume音频音频。

  除此这外,VideoPlayer组件还有很多供脚本调用的属性、方法及事件,常用的主要包括:

名称类型描述
EnableAudioTrack方法启用或禁用音轨,需要在视频播放前设置。
Play方法播放视频。
Pause方法暂停视频播放。
Stop方法方法
isPlaying属性视频是否正在播放。
isLooping属性视频是否是循环播放 。
isPrepared属性视频是否已准备好(如加载是否完成可供播放)。
errorReceived事件发生错误时回调。
frameDropped事件丢帧时回调。
frameReady事件新帧准备好时回调,这个回调会非常频繁,使用需要谨慎。
loopPointReached事件视频播放结束时回调。
prepareCompleted事件视频资源准备好时回调。
started事件视频开始播放后回调。

  VideoPlayer还有很多其他方法、属性、事件,利用这些方法属性可以开发出功能强大的视频播放器。如前所述,VideoPlayer会调用运行时本地系统中的原生解码器,因此为确保在特定平台视频播放正常,需要提前了解运行系统的解码能力,通常,不同的操作系统对视频的原生解码并不相同,下表为当前各大系统对视频格式的原生支持列表。

操作系统支持的原生解码格式
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
Android.3gp,.mp4 ,.webm, .ts, .mkv
iPhone.m4v, .mp4, .mov

  特别需要提醒的是:即使视频后辍格式相同也不能确保一定能解码,因为同一种格式会有若干种编码方式,具体使用过程中需要查询特定平台的解码格式。

(二)实现视频播放

  因为AR中场景是实景的特殊性,以虚拟物体作为视频播放承载物是最好的选择。使用UI及摄像机平面播放模式不太适合AR应用,视频渲染模型使用Material Override非常有利用在模型特定区域播放视频。因此首先我们需要制作一个预制体,在模型的特定区域采用Material Override模式播放视频。

  新建一个工程,并在Hierarchy窗口中新建一个空对象,命名为TVs,将电视机模型文件拖放到该空对象下作为其子对象并调整好大小尺寸,然后新建一个Quad,用这个Quad为作视频播放的载体,调整该Quad到电视机屏幕位置,处理好尺寸与位置关系。因为我们采用Material Override模式,所以我们需要新建一个材质,命名为videos,该材质直接选用Standard着色器,但不赋任何纹理及参数(因为后面我们将使用视频帧作为纹理渲染到材质上),并将该材质赋给Quad对象。最后一步,为Quad对象挂载VideoPlayer组件,并设置好视频源等属性,如下图所示。

在这里插入图片描述
  将TVs制作成Prefab,同时删除Hierarchy场景中的TVs对象。为将虚拟电视机放置到真实环境中,我们采取与以晚一样的射线检测放置方式,新建一个C#脚本,命名为AppController,编写如下代码:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.UI;

[RequireComponent(typeof(ARRaycastManager))]
public class AppControler : MonoBehaviour
{
    public  GameObject spawnPrefab;
    public int MaxTVnumber = 1;
    public Button BtnPlay;
    public Button BtnPause;
    public Button BtnStop;

    static List<ARRaycastHit> Hits;
    private ARRaycastManager mRaycastManager;
    private GameObject spawnedObject = null;
    private ARPlaneManager mARPlaneManager;
    private int mCurrentTVnumber = 0;
    private UnityEngine.Video.VideoPlayer mVideoPlayer ;

    private void Start()
    {
        Hits = new List<ARRaycastHit>();
        mRaycastManager = GetComponent<ARRaycastManager>();
        mARPlaneManager = GetComponent<ARPlaneManager>();    
        BtnPlay.transform.GetComponent<Button>().onClick.AddListener(()=> mVideoPlayer.Play());
        BtnPause.transform.GetComponent<Button>().onClick.AddListener(() => mVideoPlayer.Pause());
        BtnStop.transform.GetComponent<Button>().onClick.AddListener(() => mVideoPlayer.Stop());
    }

    void Update()
    {
        if (Input.touchCount == 0)
            return;
        var touch = Input.GetTouch(0);
        if (mRaycastManager.Raycast(touch.position, Hits, TrackableType.PlaneWithinPolygon | TrackableType.PlaneWithinBounds) )
        {
            var hitPose = Hits[0].pose;
            if (spawnedObject == null && mCurrentTVnumber < MaxTVnumber)
            {
                spawnedObject = Instantiate(spawnPrefab, hitPose.position, hitPose.rotation);
                mVideoPlayer = spawnedObject.gameObject.transform.Find("Quad").gameObject.GetComponent<UnityEngine.Video.VideoPlayer>();
                TrunOffPlaneDetect();
                mCurrentTVnumber++;
            }
            else
            {
                spawnedObject.transform.position = hitPose.position;
            }
        }
    }

    void TrunOffPlaneDetect()
    {
        mARPlaneManager.enabled = false;
        foreach (var plane in mARPlaneManager.trackables)
            plane.gameObject.SetActive(false);
    }
}

  在上述代码中,我们首先定义了三个按钮(分别用于控制视频播放、暂停、停止)及最大可放置虚拟电视机的数量(视频解码也是一项计算密集型任务,过多的虚拟电视播放视频会严重应用程序性能),然后使用射线检测的方式放置虚拟电视模型,并在放置模型后停止平面检测和已检测到的平面的显示。

  将AppController脚本挂载到Hierarchy场景中的AR Session Origin对象上,然后需要在场景中新建三个UI按钮,并设置好脚本的相应属性(将之前制作的TVs预制体设置到Spawn Prefab属性,将三个按钮设置到对应的按钮属性),如下图所示。

在这里插入图片描述

  编译运行,在检测到平面后点击加载虚拟电视机,这时电视机上会播放设定的视频,可以通过按钮控制视频的播放、暂停与停止,效果如下图所示。

在这里插入图片描述
  在播放视频时,如果不勾选禁音,音频是可以同步播放的,但播放的音频并不具备空间定位能力,即声音不会呈现空间特性,在AR中实现3D音频功能需要与前文所述的空间音频组件配合使用。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_DavidWang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值