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

C# 获得最近目标的最有效方法是什么,c#,unity3d,unityscript,gameobject,C#,Unity3d,Unityscript,Gameobject,从这两种方法中获得最接近目标的最有效和最便宜的方法是什么 使用LINQ GameObject FindClosestTarget(string trgt) { GameObject[] closestGameObject = GameObject.FindGameObjectsWithTag(trgt) .OrderBy(go => Vector3.Distance(go.transform.position, transform.po

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

使用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;
     }
GameObject FindClosestTarget(字符串trgt)
{
GameObject[]gos=GameObject.FindGameObjectsWithTag(trgt);
游戏对象最近=空;
浮动距离=数学无穷大;
矢量3位置=变换位置;
foreach(游戏对象进入gos){
Vector3 diff=go.transform.position-位置;
浮动电流距离=差值sqrMagnitude;
if(电流距离<距离){
最近的=去;
距离=距离;
}
}
返回最近的位置;
}
编辑: 正如Corey所说,这个答案没有考虑到较低的方法是使用sqrt,这肯定会使其速度变慢

我不认为两者之间的区别很重要,但就原始速度而言,我认为第二个会稍微快一点,因为您没有对整个列表进行排序(最佳时间复杂度O(n*log(n)),而是只得到距离最近的列表(O(n))


然而,如果这不是计划中的一个真正关键点,我总是会选择第一个。。。第一个例子使用的是
Vector3.Distance
,这需要一个非常昂贵的
Sqrt
操作,而第二个例子使用的代码我更喜欢使用更简单的LINQ形式

以下是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代码转换为非常有效的输出


顺便说一句,如果你想将你的范围限制在一个特定的最大距离,将该距离平方,并将其与
sqrmaginality
进行比较,以避免邪恶的
Sqrt
,如果你有太多游戏对象,并且只想为一个对象找到最近的对象,而不是检查所有对象并比较它们。你可以使用触发器。将球体碰撞器连接到您的玩家并增大其大小,直到它碰撞到任何其他游戏对象


不要认为若你们使用对撞机,情况会更糟。试试看,我认为这将是一个更好的方法。(但正如我所说,如果要检查的对象太多)

没有本质区别。前者使用LINQ,这在语法上更好。您可以使用Debug.log和Time.DeltaTime检查这一点,后者更快,哪一个最快?cpu使用率降低一个?编辑了post:LINQ,而不是link.OrderBy要慢得多。(是的,速度要慢很多,但你感觉不到,因为今天的处理器真的很快!)。如果您担心性能,请将linq版本保留在注释中,但使用第二个版本,这样您就不会忘记正在发生的事情。在这种情况下,Orderby/sort是无关紧要的。最昂贵的是距离的计算。所以差别可能很小。@David我不熟悉unity,所以我想你是对的。然而,由于在这两种情况下都必须计算距离,唯一重要的是gis设置的速度(这是他要求的)。此外,当您有很多目标要比较时,sort()将变得越来越容易识别。正如我提到的,我仍然同意您使用LinQYou不认为避免
Sqrt
会让事情加快一点吗?性能并不完全取决于复杂程度:P