private void UpdateSmoothedMovementDirection() {
bool grounded = IsGrounded();
// Forward vector relative to the camera along the x-z plane
Vector3 forward = Camera.transform.TransformDirection(Vector3.forward);
forward.y = 0;
forward = forward.normalized;
// Right vector relative to the camera
// Always orthogonal to the forward vector
Vector3 right = new Vector3(forward.z, 0, -forward.x);
float v = Input.GetAxisRaw("Vertical");
float h = Input.GetAxisRaw("Horizontal");
// Are we moving backwards or looking backwards
if (v < -0.2f) {
_movingBack = true;
} else {
_movingBack = false;
}
bool wasMoving = _isMoving;
_isMoving = Mathf.Abs(h) > 0.1f || Mathf.Abs(v) > 0.1f;
// Target direction relative to the camera
Vector3 targetDirection = h * right + v * forward;
// Grounded controls
if (grounded) {
// Lock camera for short period when transitioning moving & standing still
_lockCameraTimer += Time.deltaTime;
if (_isMoving != wasMoving) {
_lockCameraTimer = 0.0f;
}
// We store speed and direction seperately,
// so that when the character stands still we still have a valid forward direction
// moveDirection is always normalized, and we only update it if there is user input.
if (targetDirection != Vector3.zero) {
// If we are really slow, just snap to the target direction
if (_moveSpeed < WalkSpeed * 0.9f && grounded) {
_moveDirection = targetDirection.normalized;
}
// Otherwise smoothly turn towards it
else {
_moveDirection = Vector3.RotateTowards(_moveDirection, targetDirection,
RotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
_moveDirection = _moveDirection.normalized;
}
}
// Smooth the speed based on the current target direction
float curSmooth = SpeedSmoothing * Time.deltaTime;
// Choose target speed
//* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f);
_characterState = CharacterState.Idle;
// Pick speed modifier
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) {
targetSpeed *= RunSpeed;
_characterState = CharacterState.Running;
} else if (Time.time - TrotAfterSeconds > _walkTimeStart) {
targetSpeed *= TrotSpeed;
_characterState = CharacterState.Trotting;
} else {
targetSpeed *= WalkSpeed;
_characterState = CharacterState.Walking;
}
_moveSpeed = Mathf.Lerp(_moveSpeed, targetSpeed, curSmooth);
// Reset walk time start when we slow down
if (_moveSpeed < WalkSpeed * 0.3f) {
_walkTimeStart = Time.time;
}
}
// In air controls
else {
// Lock camera while in air
if (_jumping) {
_lockCameraTimer = 0.0f;
}
if (_isMoving) {
_inAirVelocity += targetDirection.normalized * Time.deltaTime * InAirControlAcceleration;
}
}
}