1、将物体的世界坐标转化为摄像机下的窗口坐标
以摄像机左下角为原点,x,y在0到1之间的一个值,z值是以摄像机为原点到物体的深度;
如果z值为负数,即物体是背朝摄像机的窗口,画面里就看不到物体;
因相机不同,同个物体同个位置转化后的坐标也不同;
Vector2 viewPos = camera.WorldToViewportPoint(worldPos);
2、获得世界场景下,相机和物体的单位向量
对相机和物体进行归一化操作
//获取相机和物体之间的单位向量
Vector3 dir = (worldPos - camTransform.position).normalized;
3、通过点积来判断物体在相机的前面还是后面
点积得到的是数值,两个单位向量进行点积可获取向量夹角值;
根据点积得到的数值正负,可判断物体是否在相机前面还是后面
//以cam方向为正方向,两个坐标都取单位化,进行点积
float dot = Vector3.Dot(camTransform.forward, dir);
注:叉积得到向量,向量垂直于a,b向量所在的平面。
可以通过叉积来判断物体b在物体a的左面还是右面;
//判断b在a的左边还是右边
Vector3.Cross(vector3 a,vector3 b);
4、判断物体是否在相机窗口前
相机视野范围是:0<=x<=1,0<=y<=1;相机前方z>0;后方z<=0;
如果,物体在相机背后(dir<0),或在相机窗口外(x<0或x>1;y<0或y>1),则看不见物体。
if (dot > 0 && viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1)
return true;
else
return false;
5、功能方法
/// <summary>
/// 判断UI是否在摄像机视野内
/// </summary>
/// <param name="worldPos">UI坐标</param>
/// <returns></returns>
public bool IsInView(Camera camera, Vector3 worldPos)
{
Transform camTransform = camera.transform;
Vector2 viewPos = camera.WorldToViewportPoint(worldPos);
Vector3 dir = (worldPos - camTransform.position).normalized;
float dot = Vector3.Dot(camTransform.forward, dir);//判断物体是否在相机前面
if (dot > 0 && viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1) return true;
else return false;
}