有关这个问题,获取主角面前的箱子或者敌人对象,我在网上看到雨松写的一段代码,把它贴在下面
using UnityEngine;
using System.Collections;
public class MyTest : MonoBehaviour {
public Transform cube;
private float distance = 5f;
void Update ()
{
Quaternion r= transform.rotation;
Vector3 f0 = (transform.position + (r *Vector3.forward) * distance);
Debug.DrawLine(transform.position,f0,Color.red);
Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);
Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);
Vector3 f1 = (transform.position + (r0 *Vector3.forward) * distance);
Vector3 f2 = (transform.position + (r1 *Vector3.forward) * distance);
Debug.DrawLine(transform.position,f1,Color.red);
Debug.DrawLine(transform.position,f2,Color.red);
Debug.DrawLine(f0,f1,Color.red);
Debug.DrawLine(f0,f2,Color.red);
Vector3 point = cube.position;
if(isINTriangle(point,transform.position,f1,f0) || isINTriangle(point,transform.position,f2,f0) )
{
Debug.Log("cube in this !!!");
}else
{
Debug.Log("cube not in this !!!");
}
}
private float triangleArea(float v0x,float v0y,float v1x,float v1y,float v2x,float v2y)
{
return Mathf.Abs((v0x * v1y + v1x * v2y + v2x * v0y
- v1x * v0y - v2x * v1y - v0x * v2y) / 2f);
}
bool isINTriangle(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2)
{
float x = point.x;
float y = point.z;
float v0x = v0.x;
float v0y = v0.z;
float v1x = v1.x;
float v1y = v1.z;
float v2x = v2.x;
float v2y = v2.z;
float t = triangleArea(v0x,v0y,v1x,v1y,v2x,v2y);
float a = triangleArea(v0x,v0y,v1x,v1y,x,y) + triangleArea(v0x,v0y,x,y,v2x,v2y) + triangleArea(x,y,v1x,v1y,v2x,v2y);
if (Mathf.Abs(t - a) <= 0.01f)
{
return true;
}else
{
return false;
}
}
}
然后我自己认为的是 先求出主角附近5米范围内的所有物体,相当于规定一个圆的范围,再获取主角与箱子之间的角度或者点乘来判断是否在主角的视角内,这样不是简单一点吗,鱼松的用了好多向量的运算和角度的计算,下面我贴一下我的代码,是lua写的
-- 得到角色附近 面前的物品
function GetInSightBoxes(hero)
local newBoxes = {}
local pos = hero:GetPosition()
local cameraController = hero.cameraController
local lookForward = cameraController.cameraTrans.forward
--local forward = cameraController.cameraTrans:TransformDirection(Vector3.forward)
for uid, box in pairs(Boxes) do
local dist = Vector3.Distance(Vector3(box.position.x, 0, box.position.z), Vector3(pos.x, 0, pos.z))
if dist < 5 then
box.distance = dist
local toOther = Vector3(box.position.x, 0, box.position.z) - Vector3(pos.x, 0, pos.z)
local angle = Vector3.Angle(toOther, lookForward)
if angle < 45 then
newBoxes[uid] = box
end
print("angle=========================="..angle)
--local dot = Vector3.Dot(forward, toOther)
end
end
return newBoxes
end
我这样写是否存在什么劣势,这种情况一般是怎么处理
两种方法都没啥问题, 从性能上考虑差别也不大,不过老师觉得你的方法更好
我觉得,你这个方法也不好,不好的关键在于你的算法的第一步——求出距离角色5米内的所有物体,这个用语言来说就是一句话的事情,但是,计算机来做的话,就是一个遍历。如何求出5米内的所有物体?那就得遍历所有物体,看他们跟角色的距离是不是小于5,事实上这个算法可以优化,比如用BSP树,8叉树,但是那样非常复杂而且即便是你优化了,也无法逃脱遍历。。
我提供一个想法:
事实上,对于绝大多数游戏来讲,发现敌人的过程,可能不需要在一帧之内就判断出结果,只要能及时发现即可。因此你可以分成好几帧去做。
我的想法核心思想还是射线算法。但是,可以将算法进行一些改进。
比如:每一帧发射n条射线,n是大于等于1的整数,具体发射多少条,可以根据机器性能来。
然后,根据扇形的角度平均分配每条射线的角度。
下一帧时,将每条射线的角度进行偏移,相当于在扇形区域中进行扫描敌人。由于是n条射线同时扫描,所以每条射线的偏移角度最大是整体角度/n。
我之前实现过的一个行为树的敌人判断节点,就是用的这种算法,实验证明,当扇形角度=90度时,n=2就可以获取很好的效果,而且发现n对性能的影响不是很大。