using OTGIntegrated.Stats; using UnityEngine; namespace OTGIntegrated.Player { [RequireComponent(typeof(CharacterController))] public sealed class PlayerController : MonoBehaviour { [Header("Movement")] [SerializeField] private float rotationSpeed = 12f; [SerializeField] private float gravity = -24f; [Header("Camera")] public Transform cameraRoot; public Camera playerCamera; [SerializeField] private Vector3 cameraOffset = new Vector3(0f, 8.5f, -12.5f); [SerializeField] private float mouseSensitivity = 2.2f; private CharacterController characterController; private PlayerStats playerStats; private Vector3 velocity; private float cameraYaw; private bool inputEnabled = true; public bool InputEnabled => inputEnabled; public void Initialize(PlayerStats stats) { playerStats = stats != null ? stats : GetComponent(); } private void Awake() { characterController = GetComponent(); if (playerStats == null) { playerStats = GetComponent(); } if (playerCamera == null) { playerCamera = Camera.main; } if (cameraRoot == null) { GameObject root = new GameObject("CameraRoot"); cameraRoot = root.transform; cameraRoot.position = transform.position; } Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } private void Update() { if (!inputEnabled) { return; } HandleCameraInput(); HandleMovement(); } private void LateUpdate() { UpdateCamera(); } public void SetInputEnabled(bool enabled) { inputEnabled = enabled; if (!enabled) { velocity.x = 0f; velocity.z = 0f; } } public Vector3 GetAimForward() { Vector3 forward = playerCamera != null ? playerCamera.transform.forward : transform.forward; forward.y = 0f; return forward.sqrMagnitude > 0.001f ? forward.normalized : transform.forward; } private void HandleCameraInput() { cameraYaw += Input.GetAxis("Mouse X") * mouseSensitivity; } private void HandleMovement() { float horizontal = Input.GetAxisRaw("Horizontal"); float vertical = Input.GetAxisRaw("Vertical"); Vector3 input = new Vector3(horizontal, 0f, vertical); input = Vector3.ClampMagnitude(input, 1f); Quaternion yawRotation = Quaternion.Euler(0f, cameraYaw, 0f); Vector3 move = yawRotation * input; float moveSpeed = playerStats != null ? playerStats.MoveSpeed : 5f; if (move.sqrMagnitude > 0.001f) { Quaternion targetRotation = Quaternion.LookRotation(move, Vector3.up); transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); } if (characterController.isGrounded && velocity.y < 0f) { velocity.y = -2f; } velocity.y += gravity * Time.deltaTime; Vector3 motion = move * moveSpeed + Vector3.up * velocity.y; characterController.Move(motion * Time.deltaTime); } private void UpdateCamera() { if (cameraRoot == null) { return; } cameraRoot.position = transform.position; cameraRoot.rotation = Quaternion.Euler(0f, cameraYaw, 0f); if (playerCamera != null) { Vector3 offset = Quaternion.Euler(0f, cameraYaw, 0f) * cameraOffset; playerCamera.transform.position = transform.position + offset; playerCamera.transform.LookAt(transform.position + Vector3.up * 1.1f); } } } }