【Unity】全景视频漫游和视点切换

前一阵子完成的一个小工程,整理一下完成过程。本笔记需要与下面的官方教程链接配套使用。

官方教程链接

官方教程基本把整个工程的实现过程讲的比较清楚了,缺点是脚本提供的不全。这份笔记主要解决以下几个问题:

  1. 全景视频播放器
  2. 视点切换
  3. 细节和特效

全景视频播放器

采用一个翻转法线的球体。

为节约计算资源,Unity和许多常见三维建模软件只渲染三维物体的外表面,这也是法线方向的表面。因为视频需要在球体内表面播放,因此需要对球体做法线翻转。

翻转法线的脚本如下(FlipNormals.cs):

using System.Collections;
using UnityEngine;

public class FlipNormals : MonoBehaviour {

	// Use this for initialization
	void Start () 
    {
        Mesh mesh = this.GetComponent<MeshFilter>().mesh;

        Vector3[] normals = mesh.normals;
        for (int i = 0; i < normals.Length; i++)
            normals[i] = -1 * normals[i];

        mesh.normals = normals;

        for (int i = 0; i < mesh.subMeshCount; i++)
        {
            int[] tris = mesh.GetTriangles(i);
            for (int j = 0; j < tris.Length; j += 3)
            {
                //swap order of tri vertices
                int temp = tris[j];
                tris[j] = tris[j + 1];
                tris[j + 1] = temp;
            }
            mesh.SetTriangles(tris, i);
        }       
	}	
}

并在球体上添置Video player的组件。

去除场景中环境光的影响,为球体添加材质,将材质球设置为:

视点切换

为了让播放器在多个视频间切换,我们使用列表(List)结构,让用户自定义需要播放的视频序列数量,并添加两个自定义方法PreviousVideo()和NextVideo(),脚本如下:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;
using UnityEngine.UI;

public class SwitchVideo : MonoBehaviour {
    
    public VideoPlayer videoPlayer;
    public AudioSource audioSource;
    public List<VideoClip> videos = new List<VideoClip>();
    public int index = 0;
    public Image fadeImage;
    // Use this for initialization
	void Start () 
    {
        videoPlayer.clip = videos[index];
        videoPlayer.Play();
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    public void PreviousVideo()
    {
        if (index == 0)
            index = videos.Count;
        index = index - 1;
        fadeImage.GetComponent<FadeAlpha>().Start();
        videoPlayer.clip = videos[index];
        videoPlayer.Play();
    }

    public void NextVideo()
    {
        if (index == videos.Count - 1)
            index = -1;
        index = index + 1;
        fadeImage.GetComponent<FadeAlpha>().Start();
        videoPlayer.clip = videos[index];
        videoPlayer.Play();
    }
}

官方教程中用到了这个脚本,但作者并没有给出细节..自己试着梳理了一下逻辑发现也并不是很复杂。将此脚本同样挂在球体视频播放器上,用两个按钮分别调用两个自定义方法,实现视频的切换功能。

细节和特效

细节和特效是为提升沉浸感服务的。

这部分包括:视频切换过程中的淡入淡出,弧形UI和树叶粒子特效。

淡入淡出

用一个图像UI元素作为转场用到的黑幕,让其挡在用户视角的前方。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class FadeAlpha : MonoBehaviour
{
    //public static FadeAlpha Instance { set; get; }

    public Image fadeImage;
    private bool isInTransition;
    private float transition;
    private float duration;

    public void Start()
    {
        isInTransition = true;
        transition = 1;
        duration = 2.0f;
    }

    private void Update()
    {
        if (!isInTransition)
            return;
        
        transition -= Time.deltaTime * (1 / duration);
        fadeImage.color = Color.Lerp(new Color(0, 0, 0, 0), Color.black, transition);

        if (transition <= 0)
        {
            isInTransition = false;
        }
    }
}

弧形UI

相比单纯的平面按钮,弧形按钮有利于增强沉浸感。

使用Curved UI这个插件来控制,操作并不复杂,官方教程里有详细说明,然而这个插件要25$..

粒子特效

使用Unity官方提供的天空特效包来在场景中加入风、树叶、云等效果。

最终效果截图:

(其实录屏呈现出来的效果更好,但是懒