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

Saj*_*ake 3 c# unity-game-engine unityscript gameobject

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

使用LINQ

GameObject FindClosestTarget(string trgt) 
{
    GameObject[] closestGameObject = GameObject.FindGameObjectsWithTag(trgt)
                      .OrderBy(go => Vector3.Distance(go.transform.position, transform.position)
                      .FirstOrDefault();
         return closestGameObject ;
}
Run Code Online (Sandbox Code Playgroud)

或这个

 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;
     }
Run Code Online (Sandbox Code Playgroud)

Cor*_*rey 9

第一个示例使用Vector3.Distance需要非常昂贵的Sqrt操作,而第二个使用代码我更喜欢抛出更简单的LINQ形式.

以下是Unity Scripting 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();
}
Run Code Online (Sandbox Code Playgroud)

两个世界中最好的...... LINQ的简单性(以及非常有效的实现)没有多余的Sqrt操作来减慢你的速度.

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

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