获得最接近目标的最有效方法是什么
本文关键字:有效 方法 是什么 最接近 目标 | 更新日期: 2023-09-27 18:17:53
从这两种方法中获取最接近目标的最有效和更便宜的方法是什么?
使用 LINQ
GameObject FindClosestTarget(string trgt)
{
GameObject[] closestGameObject = GameObject.FindGameObjectsWithTag(trgt)
.OrderBy(go => Vector3.Distance(go.transform.position, transform.position)
.FirstOrDefault();
return closestGameObject ;
}
或者这个
GameObject FindClosestTarget(string trgt)
{
GameObject[] gos= GameObject.FindGameObjectsWithTag(trgt);
GameObject closest=null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
foreach (GameObject go in gos) {
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance) {
closest = go;
distance = curDistance;
}
}
return closest;
}
第一个示例使用需要相当昂贵的Sqrt
操作的Vector3.Distance
,而第二个示例使用我更愿意抛出的代码,以支持更简单的 LINQ 形式。
以下是 Unity 脚本 API 文档的摘录,供sqrMagnitude
使用:
向量 v 的大小计算为
Mathf.Sqrt(Vector3.Dot(v, v))
。但是,Sqrt
计算非常复杂,并且执行时间比正常的算术运算更长。计算平方幅度而不是使用幅度属性要快得多 - 计算基本相同,只是没有慢Sqrt
调用。如果您只是使用幅度来比较距离,那么您也可以将平方幅度与距离平方进行比较,因为比较将给出相同的结果。
所以你的方案基本上正是他们创建sqrMagnitude
属性的原因......因为Sqrt
是一项昂贵的操作,如果您只想知道距离的顺序而不需要实际距离以供以后使用,则不需要它。
就个人而言,我更喜欢将其作为第三种选择:
GameObject FindClosestTarget(string trgt)
{
Vector3 position = transform.position;
return GameObject.FindGameObjectsWithTag(trgt)
.OrderBy(o => (o.transform.position - position).sqrMagnitude)
.FirstOrDefault();
}
两全其美。。。LINQ 的简单性(和相当高效的实现(,没有多余的Sqrt
操作来减慢您的速度。
但与往常一样,当您对代码的实际性能有疑问时,您应该对每种方法进行一些仔细的分析,以查看哪种方法实际上性能更好。 有时,优化器会抛出一个曲线球,并将可怕的 C# 代码转换为非常有效的输出。
顺便说一句,如果您想将范围限制为特定的最大距离,请将该距离平方并将其与sqrMaginitude
进行比较以避免邪恶Sqrt
。
编辑:正如 Corey 所建议的那样,这个答案没有考虑到较低的方法使用的是 sqrt,这肯定会使其变慢。
我不认为差异很重要,但就原始速度而言,我认为第二个会稍微快一些,因为您不会对整个列表进行排序(最佳时间复杂度 O(n*log(n(((,而只得到距离最近的一个 (O(n((。
但是,如果这不是程序中真正关键的一点,我总是会选择第一个......只是好多了。
如果您有太多的游戏对象,并且只想为一个对象找到最近的对象,而不是检查所有对象并进行比较。 您可以使用触发器。将球体碰撞体附加到玩家并增加其大小,直到它与任何其他游戏对象碰撞。
不要以为如果你使用对撞机,情况会更糟。尝试一下,我认为这将是一个更好的方法。(但正如我所说,如果你有太多对象要检查(