Суть в том, что в коде вектор движения рассчитывается относительно ориентации камеры, а не относительно персонажа. То есть, при получении направления движения используются следующие строки:
var cameraForward = Camera.main.transform.forward;
var cameraRight = Camera.main.transform.right;
Далее, вектор движения составляется из комбинации этих направлений:
moveDirection = (cameraForward * moveVertical) + (cameraRight * moveHorizontal);
Это означает, что если камера поворачивается на 180 градусов (например, вместе с персонажем), то направление «вперёд» для камеры оказывается противоположным тому, что может ожидаться, если бы управление было привязано к направлению взгляда персонажа. В результате при нажатии на клавишу, отвечающую за движение вперёд, персонаж двигается в направлении, противоположном ожидаемому.
Чтобы убрать «реверсивное» поведение управления, можно сделать одно из двух:
1) Привязать расчёт направления движения к персонажу, а не к камере. Например, использовать transform.forward и transform.right персонажа:
moveDirection = (transform.forward * moveVertical) + (transform.right * moveHorizontal);
Тогда нажатие «вперёд» всегда будет двигаться в направлении взгляда персонажа.
2) Либо, если требуется управление с учётом ориентации камеры (например, в третьем лице), можно отдельно вычислять разницу между направлением персонажа и направлением камеры и скорректировать ввод так, чтобы он был более интуитивным для игрока.
public class Player : MonoBehaviour
{
public float speed = 5.0f;
public float jumpHeight = 2.0f;
private CharacterController controller;
private Vector3 moveDirection = Vector3.zero ;
private float gravity = 9.81f;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
if (controller.isGrounded)
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
// Получаем текущую ориентацию камеры
var cameraForward = Camera.main.transform.forward;
var cameraRight = Camera.main.transform.right;
// Исключаем компоненту вверх-вниз у вектора вперед камеры, чтобы избежать движения вверх/вниз
cameraForward.y = 0f;
cameraForward.Normalize();
// Создаем новый вектор движения, основанный на ориентации камеры
moveDirection = (cameraForward * moveVertical) + (cameraRight * moveHorizontal);
moveDirection *= speed;
if (Input.GetButton("Jump"))
{
moveDirection.y = Mathf.Sqrt(jumpHeight * 2.0f * gravity);
}
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
}