提问者:小点点

统一,如何将相机切换到第二个对象的位置?


我在Unity 3D中遇到了一个奇怪的问题。我的想法是从阵列中找到距离玩家最近和第二最近的对象。然后我想让相机移动到最近的物体的位置,看着播放器,但是如果播放器和最近的物体之间的距离太小,我想让相机移动到第二个物体的位置。我做了一些编码,我不知道为什么else-if的第三部分甚至没有执行。当玩家离得太近时,相机不会切换,而是保持最近的物体位置。

public class Robot2 : MonoBehaviour
{
public GameObject cameraHolder;
public Transform[] objects;
private Transform nearestObj;

private Transform secondObj;
void Update()
{
    float lowestDist = 9999f;
    float secondLowestDist = lowestDist + 1f;
    float tooCloseDist = 3f;
    nearestObj = null;
    secondObj = null;
    
    foreach(Transform obj in objects)
    {
        float dist = Vector3.Distance(transform.position, obj.position);
        if(dist < lowestDist)
        {
            lowestDist = dist;
            nearestObj = obj;
            cameraHolder.transform.position = nearestObj.transform.position;      

        }
        else if(dist < secondLowestDist)
        {
            secondLowestDist = dist;
            secondObj = obj;

        }
        else if(dist < tooCloseDist)
        {
            Debug.Log("Too close , switching");
            cameraHolder.transform.position = secondObj.transform.position;
        }
    }
    Debug.DrawLine(transform.position, nearestObj.transform.position, Color.red);
}

}


共1个答案

匿名用户

如果第二个对象也太近怎么办?

在使用和访问第一个和第二个最近的对象之前,为了获得更一般的解决方案,我将首先遍历整个阵列,看看是否真的没有更接近的对象。

您可以使用LinqOrderBy,并使用(transform.position-obj.position)作为标准。SQR幅度比使用幅度更便宜(这是矢量3.距离使用的)

using System.Linq;

...

[SerializeField] float tooCloseDist = 3f;

// Just a little helper struct, could also use a tuple 
// but this is probably easier to understand
private struct DistanceInfo
{
    public readonly Transform transform;
    public readonly float sqrDistance;

    public DistanceInfo(Transform self, Transform target)
    {
        transform = target;
        sqrDistance = (self.position - target.position).sqrMagnitude;
    }
}

private void Update ()
{
    // It's cheaper to use squared magnitude of vectors if it is only about comparing them
    var tooCloseDistanceSqr = tooCloseDistance * tooCloseDistance;

    // In one go for each object get according distance info instance
    // and order them starting with the smallest distance
    var orderedByDistance = objects.Select(obj => new DistanceInfo (transform, obj)).OrderBy(info => info.sqrDistance);

    // Go through the sorted instances of DistanceInfo
    foreach(var info in orderedByDistance)
    {
        // since we ordered by distance "info" is always the next closest object
        // if it is too close -> skip to the next closest one
        if(info.sqrDistance < tooCloseDistanceSqr) continue;
  
        // we found the next closest object that is not too close
        cameraHolder.transform.position = info.transform.position; 
        Debug.DrawLine(transform.position, info.transform.position, Color.red);
       
        // break the loop as we don't want to do anything further
        break;
    }
}