获得最接近目标的最有效方法是什么

时间:2015-10-15 09:54:15

标签: c# unity3d unityscript gameobject

从这两种方法中获得最接近目标的最有效和最便宜的方法是什么?

使用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;
     }

3 个答案:

答案 0 :(得分:8)

第一个例子使用previous = None current = object() while previous != current: previous = current current = ... ,这需要一个非常昂贵的Vector3.Distance操作,而第二个例子使用的代码我更倾向于使用更简单的LINQ格式。

以下摘自sqrMagnitude的Unity Scripting API文档:

  

矢量v的大小计算为Sqrt。但是,Mathf.Sqrt(Vector3.Dot(v, v))计算非常复杂,执行时间比正常的算术运算要长。计算平方幅度而不是使用幅度属性要快得多 - 仅在没有慢Sqrt调用的情况下计算基本相同。如果你只是使用幅度来比较距离,那么你也可以将平方幅度与距离的平方进行比较,因为比较会给出相同的结果。

因此,您的场景基本上就是他们创建Sqrt属性的原因...因为sqrMagnitude是一项昂贵的操作,如果您只是想知道距离的顺序而不需要它就不需要实际距离以供日后使用。

我个人更喜欢这个作为第三种选择:

Sqrt

两全其美...... LINQ的简单性(以及非常高效的实现),没有多余的GameObject FindClosestTarget(string trgt) { Vector3 position = transform.position; return GameObject.FindGameObjectsWithTag(trgt) .OrderBy(o => (o.transform.position - position).sqrMagnitude) .FirstOrDefault(); } 操作来减慢你的速度。

但与往常一样,当您对代码的真实性能有疑问时,您应该对每种方法进行一些仔细的分析,以确定哪种方法实际上表现更好。有时优化器会抛出一个曲线球并将可怕的C#代码转换为非常有效的输出。

顺便提一下,如果您想将范围限制在特定的最大距离,请将该距离平方并将其与Sqrt进行比较,以避免邪恶的sqrMaginitude

答案 1 :(得分:3)

编辑: 正如Corey所说,这个答案没有考虑到较低的方法是使用sqrt,这肯定会使它变慢。

我不认为差异是至关重要的,但就原始速度而言,我认为第二个会略快一些,因为你没有整理整个列表(最佳时间复杂度O(n * log) (n))),但只获得距离最近的那个(O(n))。

然而,如果它不是该计划中真正关键的一点,我会永远选择第一个...它只是更好。

答案 2 :(得分:1)

如果您有太多的游戏对象,并且想要仅为一个对象找到最近的对象,而不是检查所有对象并进行比较。你可以使用触发器。将球形碰撞器连接到您的播放器并增加其大小,直到它碰撞任何其他游戏对象。

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