我在 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);
}
}
如果第二个物体也太近怎么办?
对于使用和访问第一个和第二个最接近的对象之前的更通用的解决方案,我将首先遍历整个数组,看看是否真的没有更接近的对象。
你可以使用Linq OrderBy https://learn.microsoft.com/dotnet/api/system.linq.enumerable.orderby并作为标准使用(transform.position - obj.position).sqrMagnitude
这比使用便宜magnitude
(这是什么Vector3.Distance
正在使用)
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;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)