转动时倾斜第一人称相机的 z 轴
Tilt first person camera's z axis while turning
我正在研究具有 boost/dash 功能的双足坦克的控制。
当通过按住按钮激活 boost/dash 模式时,坦克从传统的 WASD 扫射运动变为类似于喷气式战斗机但在地面上的运动。
现在,当玩家试图在加速时转弯时,相机需要随着转弯方向倾斜,以使其感觉更顺畅。
Here is a video clip showing my problem
这是添加到主摄像头的脚本
public class PlayerCameraTilt : MonoBehaviour
{
private Camera viewCam;
private CharacterController characterController;
public float tiltAmount = 10f;
private void Start()
{
viewCam = GetComponent<Camera>();
characterController = GetComponentInParent<CharacterController>();
}
private void Update()
{
if (characterController.GetComponent<PlayerController>().movementState == MovementModes.boost)
{
float inputValue = Input.GetAxis("MoveHorizontal") * tiltAmount;
Vector3 euler = transform.localEulerAngles;
euler.z = Mathf.Lerp(euler.z, -inputValue, 5f * Time.deltaTime);
transform.localEulerAngles = euler;
}
else
{
Vector3 euler = transform.localEulerAngles;
euler.z = Mathf.Lerp(euler.z, 0f, 5f * Time.deltaTime);
transform.localEulerAngles = euler;
}
}
}
有点效果,但只能在一个旋转方向上,即正方向。如果我转向另一个方向,角度变为负值并进行整个 360 度旋转,直到它以 0 度结束。
我尝试使用内置的四元数方法,例如 Quaternion.Rotate() 或 Quaternion.AngleAxis()
但它们不起作用,因为 Quaternion.Rotate() 不会倾斜相机,而是完全旋转它。 Quaternion.AngleAxis() 适用于整个倾斜角度限制,但也会对我不想修改的另一个轴做一些事情。
有什么方法可以防止当轴输入为负值,只是稍微倾斜一个角度时,相机就不会做完整的 360° 旋转吗?
撇开环绕问题不谈,z 组件是 "applied" 欧拉组件中的第一个,因此我不会像在本应用程序中那样直接修改它。
相反,我会将输入转换为倾斜角度,在应用 localRotation (Quaternion.Inverse(transform.localRotation) * transform.up
) 之前将局部向上旋转该角度,然后使用 Quaternion.LookRotation
找到一个旋转当前向前和向上,然后使用 Quaternion.Slerp
向该旋转旋转:
private void Update()
{
if (characterController.GetComponent<PlayerController>().movementState == MovementModes.boost)
{
float inputValue = Input.GetAxis("MoveHorizontal") * tiltAmount;
Vector3 upOfParent = Quaternion.Inverse(transform.localRotation) * transform.up;
Vector3 upDir = Quaternion.AngleAxis(-inputValue, transform.forward) * upOfParent;
Quaternion goalRot = Quaternion.LookRotation(transform.forward, upDir);
transform.rotation = Quaternion.Slerp(transform.rotation, goalRot, 5f * Time.deltaTime);
}
else
{
float inputValue = Input.GetAxis("MoveHorizontal") * tiltAmount;
Vector3 upOfParent = Quaternion.Inverse(transform.localRotation) * transform.up;
Quaternion goalRot = Quaternion.LookRotation(transform.forward, upOfParent);
transform.rotation = Quaternion.Slerp(transform.rotation, goalRot, 5f * Time.deltaTime);
}
}
请记住,对 lerp/slerp 操作使用 t = 5f * Time.deltaTime
并不总是保证输出永远等于 to
参数。
我正在研究具有 boost/dash 功能的双足坦克的控制。 当通过按住按钮激活 boost/dash 模式时,坦克从传统的 WASD 扫射运动变为类似于喷气式战斗机但在地面上的运动。 现在,当玩家试图在加速时转弯时,相机需要随着转弯方向倾斜,以使其感觉更顺畅。
Here is a video clip showing my problem
这是添加到主摄像头的脚本
public class PlayerCameraTilt : MonoBehaviour
{
private Camera viewCam;
private CharacterController characterController;
public float tiltAmount = 10f;
private void Start()
{
viewCam = GetComponent<Camera>();
characterController = GetComponentInParent<CharacterController>();
}
private void Update()
{
if (characterController.GetComponent<PlayerController>().movementState == MovementModes.boost)
{
float inputValue = Input.GetAxis("MoveHorizontal") * tiltAmount;
Vector3 euler = transform.localEulerAngles;
euler.z = Mathf.Lerp(euler.z, -inputValue, 5f * Time.deltaTime);
transform.localEulerAngles = euler;
}
else
{
Vector3 euler = transform.localEulerAngles;
euler.z = Mathf.Lerp(euler.z, 0f, 5f * Time.deltaTime);
transform.localEulerAngles = euler;
}
}
}
有点效果,但只能在一个旋转方向上,即正方向。如果我转向另一个方向,角度变为负值并进行整个 360 度旋转,直到它以 0 度结束。
我尝试使用内置的四元数方法,例如 Quaternion.Rotate() 或 Quaternion.AngleAxis() 但它们不起作用,因为 Quaternion.Rotate() 不会倾斜相机,而是完全旋转它。 Quaternion.AngleAxis() 适用于整个倾斜角度限制,但也会对我不想修改的另一个轴做一些事情。
有什么方法可以防止当轴输入为负值,只是稍微倾斜一个角度时,相机就不会做完整的 360° 旋转吗?
撇开环绕问题不谈,z 组件是 "applied" 欧拉组件中的第一个,因此我不会像在本应用程序中那样直接修改它。
相反,我会将输入转换为倾斜角度,在应用 localRotation (Quaternion.Inverse(transform.localRotation) * transform.up
) 之前将局部向上旋转该角度,然后使用 Quaternion.LookRotation
找到一个旋转当前向前和向上,然后使用 Quaternion.Slerp
向该旋转旋转:
private void Update()
{
if (characterController.GetComponent<PlayerController>().movementState == MovementModes.boost)
{
float inputValue = Input.GetAxis("MoveHorizontal") * tiltAmount;
Vector3 upOfParent = Quaternion.Inverse(transform.localRotation) * transform.up;
Vector3 upDir = Quaternion.AngleAxis(-inputValue, transform.forward) * upOfParent;
Quaternion goalRot = Quaternion.LookRotation(transform.forward, upDir);
transform.rotation = Quaternion.Slerp(transform.rotation, goalRot, 5f * Time.deltaTime);
}
else
{
float inputValue = Input.GetAxis("MoveHorizontal") * tiltAmount;
Vector3 upOfParent = Quaternion.Inverse(transform.localRotation) * transform.up;
Quaternion goalRot = Quaternion.LookRotation(transform.forward, upOfParent);
transform.rotation = Quaternion.Slerp(transform.rotation, goalRot, 5f * Time.deltaTime);
}
}
请记住,对 lerp/slerp 操作使用 t = 5f * Time.deltaTime
并不总是保证输出永远等于 to
参数。