Untitled
unknown
plain_text
a year ago
7.6 kB
9
Indexable
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Jiya.FinalCC
{
[DefaultExecutionOrder(-1)]
public class PlayerController : MonoBehaviour
{
#region Class Variables
[Header("Components")]
[SerializeField] private CharacterController _characterController;
[SerializeField] private Camera _playerCamera;
public float RotationMismatch {get; private set;} = 0f;
public bool IsRotatingToTarget {get; private set;} = false;
[Header("Base Movement")]
public float runAcceleration = 35f;
public float runSpeed = 4f;
public float sprintAccelerataion = 50f;
public float sprintSpeed = 7f;
public float drag = 20f;
public float gravity = 25f;
public float jumpSpeed = 1.0f;
public float movingThreshold = 0.01f;
[Header("Animation")]
public float playerModelRotationSpeed = 10f;
public float rotateToTargetTime = 0.25f;
[Header("Camera Settings")]
public float lookSenseH = 0.1f;
public float lookSenseV = 0.1f;
public float lookLimitV = 89f;
private PlayerLocomotionInput _playerLocomotionInput;
private PlayerState _playerState;
private Vector2 _cameraRotation = Vector2.zero;
private Vector2 _playerTargetRotation = Vector2.zero;
private float _rotatingToTargetTimer = 0f;
private float _verticalVelocity = 0f;
#endregion
#region Startup
private void Awake()
{
_playerLocomotionInput = GetComponent<PlayerLocomotionInput>();
_playerState = GetComponent<PlayerState>();
}
#endregion
#region Update Logic
private void Update()
{
UpdateMovementState();
HandleVerticalMovement();
HandleLateralMovement();
}
private void UpdateMovementState()
{
bool isMovementInput = _playerLocomotionInput.MovementInput != Vector2.zero; //order
bool isMovingLaterally = IsMovingLaterally(); //matter
bool isSprinting = _playerLocomotionInput.SprintToggledOn && isMovingLaterally; //order matters
bool isGrounded = IsGrounded();
PlayerMovementState lateralState = isSprinting ? PlayerMovementState.Sprinting :
isMovingLaterally || isMovementInput ? PlayerMovementState.Running : PlayerMovementState.Idling;
_playerState.SetPlayerMovementState(lateralState);
// Control Airborn State
if (!isGrounded && _characterController.velocity.y > 0f)
{
_playerState.SetPlayerMovementState(PlayerMovementState.Jumping);
}
else if (!isGrounded && _characterController.velocity.y <= 0f)
{
_playerState.SetPlayerMovementState(PlayerMovementState.Falling);
}
}
private void HandleVerticalMovement()
{
bool isGrounded = _playerState.InGroundedState();
if (isGrounded && _verticalVelocity < 0)
_verticalVelocity = 0f;
_verticalVelocity -= gravity * Time.deltaTime;
if (_playerLocomotionInput.JumpPressed && isGrounded)
{
_verticalVelocity += Mathf.Sqrt(jumpSpeed * 3 * gravity);
}
}
private void HandleLateralMovement()
{
// Create quick references for current state
bool isSprinting = _playerState.CurrentPlayerMovementState == PlayerMovementState.Sprinting;
bool isGrounded = _playerState.InGroundedState();
// State dependent acceleration and speed
float lateralAcceleration = isSprinting ? sprintAccelerataion : runAcceleration;
float clampLateralMagnitude = isSprinting ? sprintSpeed : runSpeed;
Vector3 cameraForwardXZ = new Vector3(_playerCamera.transform.forward.x, 0f, _playerCamera.transform.forward.z).normalized;
Vector3 cameraRightXZ = new Vector3(_playerCamera.transform.right.x, 0f, _playerCamera.transform.right.z).normalized;
Vector3 movementDirection = cameraRightXZ * _playerLocomotionInput.MovementInput.x + cameraForwardXZ * _playerLocomotionInput.MovementInput.y;
Vector3 movementDelta = movementDirection * lateralAcceleration * Time.deltaTime;
Vector3 newVelocity = _characterController.velocity + movementDelta;
// Add drag to player
Vector3 currentDrag = newVelocity.normalized * drag * Time.deltaTime;
newVelocity = (newVelocity.magnitude > drag * Time.deltaTime) ? newVelocity - currentDrag : Vector3.zero;
newVelocity = Vector3.ClampMagnitude(newVelocity, clampLateralMagnitude);
newVelocity.y += _verticalVelocity;
// Move character (Unity suggests only calling this once per tick)
_characterController.Move(newVelocity * Time.deltaTime);
}
#endregion
#region Late Update Logic
private void LateUpdate()
{
UpdateCameraRotation();
}
private void UpdateCameraRotation()
{
_cameraRotation.x += lookSenseH * _playerLocomotionInput.LookInput.x;
_cameraRotation.y = Mathf.Clamp(_cameraRotation.y - lookSenseV * _playerLocomotionInput.LookInput.y, -lookLimitV, lookLimitV);
_playerTargetRotation.x += transform.eulerAngles.x + lookSenseH * _playerLocomotionInput.LookInput.x;
float rotationTolerance = 90f;
bool isIdling = _playerState.CurrentPlayerMovementState == PlayerMovementState.Idling;
IsRotatingToTarget = _rotatingToTargetTimer > 0;
if ( !isIdling || Mathf.Abs(RotationMismatch) > rotationTolerance || IsRotatingToTarget)
{
Quaternion targetRotationX = Quaternion.Euler(0f, _playerTargetRotation.x, 0f);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotationX, playerModelRotationSpeed * Time.deltaTime);
if (Mathf.Abs(RotationMismatch) > 90f)
{
_rotatingToTargetTimer = rotateToTargetTime;
}
_rotatingToTargetTimer -= Time.deltaTime;
}
_playerCamera.transform.rotation = Quaternion.Euler(_cameraRotation.y, _cameraRotation.x, 0f);
Vector3 camForwardProjectedXZ = new Vector3(_playerCamera.transform.forward.x, 0f, _playerCamera.transform.forward.z).normalized;
Vector3 crossProduct = Vector3.Cross(transform.forward, camForwardProjectedXZ);
float sign = Mathf.Sign(Vector3.Dot(crossProduct, transform.up));
RotationMismatch = sign * Vector3.Angle(transform.forward, camForwardProjectedXZ);
}
#endregion
#region State Checks
private bool IsMovingLaterally()
{
Vector3 lateralVelocity = new Vector3(_characterController.velocity.x, 0f, _characterController.velocity.y);
return lateralVelocity.magnitude > movingThreshold;
}
private bool IsGrounded()
{
return _characterController.isGrounded;
}
#endregion
}
}
Editor is loading...
Leave a Comment