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

本文关键字:有效 方法 是什么 最接近 目标 | 更新日期: 2023-09-27 18:17:53

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

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

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

第一个示例使用需要相当昂贵的Sqrt操作的Vector3.Distance,而第二个示例使用我更愿意抛出的代码,以支持更简单的 LINQ 形式。

以下是 Unity 脚本 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();
}

两全其美。。。LINQ 的简单性(和相当高效的实现(,没有多余的Sqrt操作来减慢您的速度。

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

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

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

我不认为差异很重要,但就原始速度而言,我认为第二个会稍微快一些,因为您不会对整个列表进行排序(最佳时间复杂度 O(n*log(n(((,而只得到距离最近的一个 (O(n((。

但是,如果这不是程序中真正关键的一点,我总是会选择第一个......只是好多了。

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

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