获得最近目标的最有效方法是啥

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】:

如果您有太多游戏对象,并且只想为一个对象找到最近的对象,而不是检查所有对象并比较它们。你可以使用触发器。将球体对撞机附加到您的玩家并增加它的大小,直到它与任何其他游戏对象发生碰撞。

不要以为如果你使用对撞机它总是会更糟。尝试一下,我认为这将是一个更好的方法。 (但正如我所说,如果您要检查的对象太多)

【讨论】:

以上是关于获得最近目标的最有效方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

发出类型声明的最有效方法是啥?

获得数年数月数的最有效方法

您可以在 Java 中获得的最接近 C# 内部修改的内容是啥?

在 SSE2 上进行无符号 64 位比较的最有效方法是啥?

在 Perl 中获得 Epoch 毫秒的最佳方法是啥?

获得所有用户使用的第一种付款方式的最有效方式