获得最近目标的最有效方法是啥
Posted
技术标签:
【中文标题】获得最近目标的最有效方法是啥【英文标题】:What is the most effective way to get closest target获得最近目标的最有效方法是什么 【发布时间】:2015-10-15 09:54:15 【问题描述】:从这两种方法中获得最近目标的最有效且成本更低的方法是什么?
使用 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;
【问题讨论】:
没有本质区别。前者使用 LINQ,语法更好。 这个你可以用 Debug.log 和 Time.DeltaTime 来检查,哪个更快 哪一个最快? cpu 使用量少一个? 编辑帖子:LINQ,而不是链接。 OrderBy 慢很多。 (是的,速度慢了很多,但你感觉不到,因为今天的处理器真的很快!)。如果您担心性能,请在评论中保留 linq 版本,但使用第二个版本,这样您就不会忘记发生了什么。 【参考方案1】:第一个示例使用Vector3.Distance
,这需要相当昂贵的Sqrt
操作,而第二个示例使用我更喜欢使用更简单的LINQ 形式的代码。
以下是 sqrMagnitude
的 Unity 脚本 API 文档摘录:
向量 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
。
【讨论】:
【参考方案2】:编辑: 正如 Corey 建议的那样,这个答案没有考虑到较低的方法正在使用 sqrt,这肯定会使其变慢。
我认为差异并不重要,但就原始速度而言,我认为第二个会稍微快一些,因为您没有对整个列表进行排序(最佳时间复杂度 O(n*log(n ))),但只得到距离最近的那个 (O(n))。
但是,如果它不是程序中真正关键的一点,我总是会选择第一个...只是更好。
【讨论】:
Orderby/sort 在这种情况下是微不足道的。最昂贵的是距离的计算。所以差别可能很小。 @David 我不熟悉统一,所以我想你是对的。然而,由于在这两种情况下都必须计算距离,唯一重要的是 gis 设置的速度(他要求)。此外,当您有很多目标要比较时, sort() 将变得越来越容易识别。正如我提到的,我仍然同意你使用 LinQ 你不认为避免Sqrt
会加快速度吗?性能不仅仅是复杂性的顺序:P【参考方案3】:
如果您有太多游戏对象,并且只想为一个对象找到最近的对象,而不是检查所有对象并比较它们。你可以使用触发器。将球体对撞机附加到您的玩家并增加它的大小,直到它与任何其他游戏对象发生碰撞。
不要以为如果你使用对撞机它总是会更糟。尝试一下,我认为这将是一个更好的方法。 (但正如我所说,如果您要检查的对象太多)
【讨论】:
以上是关于获得最近目标的最有效方法是啥的主要内容,如果未能解决你的问题,请参考以下文章