FlyCamera 与碰撞

FlyCamera with collision

如何在 Unity 3d 中为飞行相机创建碰撞?防止摄像机掉落到现场的物体上。我的相机脚本片段:

public class FlyCamera : MonoBehaviour
{
void FixedUpdate()
{
   if (!isAlternative)
        SetCameraMovement();
}
private void SetCameraMovement()
{
    lastMouse = Input.mousePosition - lastMouse;
    lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0);
    lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x, transform.eulerAngles.y + lastMouse.y, 0);
    if (Input.GetMouseButton(1))
        transform.eulerAngles = lastMouse;
    lastMouse = Input.mousePosition;
    GetBaseInput();
    transform.position = Vector3.Lerp(transform.position, NewPosition, Time.deltaTime * movementTime);
}

private void GetBaseInput()
{
    Speed = Input.GetKey(KeyCode.LeftShift) ? superSpeed : mainSpeed;
    if (Input.GetKey(KeyCode.W))
        NewPosition += transform.forward * Speed;
    if (Input.GetKey(KeyCode.S))
        NewPosition += transform.forward * -Speed;
    if (Input.GetKey(KeyCode.A))
        NewPosition += transform.right * -Speed;
    if (Input.GetKey(KeyCode.D))
        NewPosition += transform.right * Speed;
}

}

最好按照 docs 中的建议将相机移动放在 LateUpdate() 中。

为碰撞检测正确设置了刚体和对撞机。检查 docs 以便您可以正确检测碰撞。

检查“注意:仅当其中一个碰撞器还附加了非运动学刚体时才会发送碰撞事件”,因此您的相机可以是一个没有刚体的游戏对象,这样您就可以自由飞行并发生碰撞。

如果您可能需要相机的物理行为,并且您希望它也像刚体一样工作,我会使用 rigidbody.SetPosition 而不是 transform.position = new Vector3() 来设置相机运动,因为您需要选择在几何或物理世界中设置变换。 另外你需要取消勾选重力选项才不会掉落。

如果你想实现一个类似 RTS 的飞行相机,你可以将相机设置为一个类似推车的父对象,并让它一直注视着那个对象:

对象(相机推车)-> 这是由 wasd 移动并旋转到所需的视角

子对象:相机 -> 只有相机的 position.y 会发生变化

然后,在 Update() 中推车上的自定义脚本上,将 LineCast 从推车发送到相机。当演员击中碰撞器时(重要的是在这里使用例如标签,这样它就不会与世界上的任何东西发生碰撞,例如单位),逐渐(随着时间的推移)减少相机的 position.y,如果没有被击中,则逐渐增加它到所需的高度。它不会完全阻止相机剪裁穿过更大的物体,而是移动它,这样它就不会停留在对撞机“内部”。类似的东西也通常用于 RPG 第三人称相机。

如果需要更多说明,请告诉我!

编辑:不过,我只会对真正大的视线阻挡物体这样做,而不是地形或更小的物体 buildings/units - 至少如果你的目标更多是 RTS 或 sim 游戏。

Edit2: 在太阳系设置中,它有点复杂。几个选项:

  1. 在平移相机之前,对所有天体 SphereColliders 执行 SphereCast(在所需的(最终)运动方向上,球体半径为到任何物体的最小允许距离)并设置你的“NewPosition”到最近的 hitPoint 减去到天体的所需最小允许距离。还要在这里添加一些边距,这样相机就不会卡住。这将是一种连续的碰撞检测方法。

  2. 每次平移相机后,对所有天体做一个CheckSphere(球体半径允许到任何物体的最小距离),只要有任何生命点,就对相机进行 lerp随着时间的推移。这是一种看起来“更柔和”的方法,但如果你飞得非常快,它仍然可以夹入某些东西。

您可以在 LateUpdate() 中同时执行这两项操作。