获取摄像机的视口区域

常用的摄像机有两种、一种是正交摄像机,另一种是透视摄像机,由于正交相机的视口范围是固定不变的,因此这里只讨论透视摄像机,它是由原点向外扩散的视锥体,这里引用下雨松MOMO的一篇博客《Unity3D研究院之获取摄像机的视口区域》中代码如下:

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

public class cameraUI : MonoBehaviour {

    private Camera theCamera;

    //距离摄像机8.5米 用黄色表示
    public float upperDistance = 8.5f;
    //距离摄像机12米 用红色表示
    public float lowerDistance = 12.0f;

    private Transform tx;
    void Start () {
        if (!theCamera)
        {
            theCamera = Camera.main;//获取MainCamera
        }
        tx = theCamera.transform;
    }
	
	// Update is called once per frame
	void Update () {
        FindUpperCorners();
        FindLowerCorners();
    }

    void FindUpperCorners()
    {
        Vector3[] corners = GetCorners(upperDistance);

        // for debugging
        Debug.DrawLine(corners[0], corners[1], Color.yellow); // UpperLeft -> UpperRight
        Debug.DrawLine(corners[1], corners[3], Color.yellow); // UpperRight -> LowerRight
        Debug.DrawLine(corners[3], corners[2], Color.yellow); // LowerRight -> LowerLeft
        Debug.DrawLine(corners[2], corners[0], Color.yellow); // LowerLeft -> UpperLeft
    }


    void FindLowerCorners()
    {
        Vector3[] corners = GetCorners(lowerDistance);

        // for debugging
        Debug.DrawLine(corners[0], corners[1], Color.red);
        Debug.DrawLine(corners[1], corners[3], Color.red);
        Debug.DrawLine(corners[3], corners[2], Color.red);
        Debug.DrawLine(corners[2], corners[0], Color.red);
    }


    Vector3[] GetCorners(float distance)
    {
        Vector3[] corners = new Vector3[4];
        
        //获取相机的视野区域角度(默认60°),取的图中对应粉红色所示角度的弧度值
        float halfFOV = (theCamera.fieldOfView * 0.5f) * Mathf.Deg2Rad;
        float aspect = theCamera.aspect;//相机的宽高比

        float height = distance * Mathf.Tan(halfFOV);//根据三角函数计算出distance距离之外的视野高度
        float width = height * aspect;//根据宽高比算出宽度

        // UpperLeft 计算视野区域左上角坐标
        corners[0] = tx.position - (tx.right * width);//x坐标
        corners[0] += tx.up * height;//y坐标
        corners[0] += tx.forward * distance;//z坐标

        // UpperRight
        corners[1] = tx.position + (tx.right * width);
        corners[1] += tx.up * height;
        corners[1] += tx.forward * distance;

        // LowerLeft
        corners[2] = tx.position - (tx.right * width);
        corners[2] -= tx.up * height;
        corners[2] += tx.forward * distance;

        // LowerRight
        corners[3] = tx.position + (tx.right * width);
        corners[3] -= tx.up * height;
        corners[3] += tx.forward * distance;

        return corners;
    }
}

算法示意图如下:

获取摄像机的视口区域

代码中distance参数即为图中1所示线条