问题描述
玩家A的可视角度为θ,可视半径为R
已知玩家A和角色B的位置和朝向
判断角色B是否在玩家A的可视距离之内
算法
在可视范围内,需要满足两个条件:
① |AB| <=R
② 向量AB与V的夹角 <= θ/2
代码(调库)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SectorJudge : MonoBehaviour
{
public GameObject target;
public float R;
public float theta;
// Update is called once per frame
void Update()
{
isVisible(R,theta,target);
}
bool isVisible(float R, float theta,GameObject target)
{
if((target.transform.position-transform.position).magnitude>R)
{
print("不在可视距离内");
return false;
}
if(Vector3.Angle(transform.forward,(target.transform.position - transform.position))>(theta/2))//须使用transform.forward,而非Vector3.forward
{
print("不在可视角度内");
return false;
}
return true;
}
}
解析
求向量AB的模 |AB|
(target.transform.position-transform.position).magnitude
求向量AB与V的夹角
Vector3.Angle(transform.forward,(target.transform.position - transform.position)
相关数学知识
1. 求向量的模
2. 求向量的夹角
a·b=|a||b|cosθ
3. 点积(数量积)
代码(手撕)
using System;
using UnityEngine;
public class SectorJudge : MonoBehaviour
{
public GameObject target;
public double R;
public double theta;
// Update is called once per frame
void Update()
{
isVisible(R,theta,target);
}
bool isVisible(double R, double theta, GameObject target)
{
if(Magnitude(target.transform.position - transform.position) > R)
{
print("不在可视距离内");
return false;
}
if(Angle(transform.forward, (target.transform.position - transform.position)) >(theta/2))
{
print("不在可视角度内");
return false;
}
return true;
}
double Magnitude(Vector3 a)
{
return Math.Sqrt((a.x*a.x)+(a.y*a.y)+(a.z*a.z));
}
double Angle(Vector3 a,Vector3 b)
{
double costheta = Dot(a,b)/ (Magnitude(a)* Magnitude(b));
return Math.Acos(costheta)*(180/3.14);
}
double Dot(Vector3 a, Vector3 b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
}
解析
点乘的库函数为Vector3.Dot(a,b)
弧度转角度,乘上Mathf.Rad2Deg,其值为180/Pi,约等于57.30
------------------------------------------------------更新------------------------------------------------------
(Unity Shader入门精要,P54)
假设,场景中有一个NPC,它位于点p处, 它的前方可以使用矢量v来表示。
问:如果现在玩家运动到了点x处, 那么如何判断玩家是在NPC的前方还是后方?
请使用数学公式来描述你的答案。
答: 使用点积来判断。
因为a·b=|a||b|cosθ,所以
cosθ = V·PX / |V||PX|;
又因为 V·PX = Vx * PXx + Vy * PXy + Vz * PXz;
如果cosθ大于0,说明θ<90°,在前面
如果cosθ小于0,说明θ>90°,在后面
问:如果现在玩家运动到了点x处, 那么如何判断玩家是在NPC的左边还是右边?
请使用数学公式来描述你的答案。
答: 使用叉积来判断。
因为|a✖️b|=|a||b|sinθ,所以
sinθ = |V✖️PX| / |V||PX|;
又因为 V✖️PX = 按以下方式计算;
如果sinθ大于0,说明0°<θ<180°,在左面
如果sinθ小于0,说明180°<θ<360°,在右面
问:现在游戏有了新的需求:NPC只能观察到有限的视角范围,这个视角的角度是φ,也就是说,NPC最多只能看到它前方左侧或右侧 φ/2角度内的物体。那么我们如何通过点积来判断NPC是否看到点x呢?
答:只需要判断夹角是否小于φ/2即可。
如果arccosθ<φ/2,则看得到
如果arccosθ>φ/2,则看不到
问:在上一问的条件上,策划又有了新的需求:
NPC的观察距离也有了限制,它只能看到固定距离R的对象,现在又该如何判断呢?
答:只需要比较PX与R的大小即可