Unity - A计划(永久有效期) 扫二维码继续学习 二维码时效为半小时

(197评价)
价格: 4431.00元
检测箱子对象是否在主角的视野中
草莓卷子kaka发起了问答2017-09-20
3
回复
435
浏览

有关这个问题,获取主角面前的箱子或者敌人对象,我在网上看到雨松写的一段代码,把它贴在下面

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

我这样写是否存在什么劣势,这种情况一般是怎么处理

所有回复
  • siki 2017-09-20

    两种方法都没啥问题,   从性能上考虑差别也不大,不过老师觉得你的方法更好

    还有-5条回复,点击查看
    你还没有登录,请先登录注册
  • sdhexu 2017-09-20

    我觉得,你这个方法也不好,不好的关键在于你的算法的第一步——求出距离角色5米内的所有物体,这个用语言来说就是一句话的事情,但是,计算机来做的话,就是一个遍历。如何求出5米内的所有物体?那就得遍历所有物体,看他们跟角色的距离是不是小于5,事实上这个算法可以优化,比如用BSP树,8叉树,但是那样非常复杂而且即便是你优化了,也无法逃脱遍历。。

    我提供一个想法:

    事实上,对于绝大多数游戏来讲,发现敌人的过程,可能不需要在一帧之内就判断出结果,只要能及时发现即可。因此你可以分成好几帧去做。

    我的想法核心思想还是射线算法。但是,可以将算法进行一些改进。

    比如:每一帧发射n条射线,n是大于等于1的整数,具体发射多少条,可以根据机器性能来。

    然后,根据扇形的角度平均分配每条射线的角度。

    下一帧时,将每条射线的角度进行偏移,相当于在扇形区域中进行扫描敌人。由于是n条射线同时扫描,所以每条射线的偏移角度最大是整体角度/n。

    我之前实现过的一个行为树的敌人判断节点,就是用的这种算法,实验证明,当扇形角度=90度时,n=2就可以获取很好的效果,而且发现n对性能的影响不是很大。

     

    • 草莓卷子kaka 2017-09-21

      嗯,你说的有道理,第一步得到附近的物品,如果物品比较多,还是会比较好性能,确实需要优化

      (0) 回复
    还有-4条回复,点击查看
    你还没有登录,请先登录注册
发表回复
你还没有登录,请先 登录或 注册!