using TMPro; using UnityEngine; using UnityEngine.InputSystem; public class PlayerMovement : MonoBehaviour { public InputActionAsset InputActions; private InputAction m_moveAction; private InputAction m_lookAction; private InputAction m_jumpAction; private InputAction m_throwAction; private InputAction m_pickupAction; private Vector2 m_moveAmt; private Vector2 m_lookAmt; private Rigidbody m_rigidbody; [Header("Camera/Head")] public Transform CameraTransform; public float MaxLookAngle = 90f; private float m_verticalRotation = 0f; public float WalkSpeed = 10; public float RotateSpeed = 5; public float JumpForce = 5; public Transform GroundCheck; public float GroundCheckRadius = 0.2f; public Animator animator; [Header("Head Settings")] public Transform Head; public float ThrowForce = 10f; public float PickupDistance = 3f; private bool m_isHeadThrown = false; private Rigidbody m_headRigidbody; private Vector3 m_headInitialLocalPos; private Quaternion m_headInitialLocalRot; private void Awake() { var map = InputActions.FindActionMap("Player"); m_moveAction = map.FindAction("Move"); m_lookAction = map.FindAction("Look"); m_jumpAction = map.FindAction("Jump"); m_throwAction = map.FindAction("Throw"); m_pickupAction = map.FindAction("Pickup"); m_rigidbody = GetComponent(); animator = GetComponent(); } private void OnEnable() { InputActions.FindActionMap("Player").Enable(); } private void OnDisable() { InputActions.FindActionMap("Player").Disable(); } void Start() { Cursor.lockState = CursorLockMode.Locked; m_headInitialLocalPos = Head.localPosition; m_headInitialLocalRot = Head.localRotation; } private void Update() { m_moveAmt = m_moveAction.ReadValue(); m_lookAmt = m_lookAction.ReadValue(); if (m_jumpAction.WasPressedThisFrame()) { Jump(); } if (m_throwAction.WasPressedThisFrame()) { ThrowHead(); } if (m_pickupAction.WasPressedThisFrame()) { TryPickupHead(); } } private void FixedUpdate() { Walking(); Rotating(); } private void Walking() { Vector3 move = transform.forward * m_moveAmt.y + transform.right * m_moveAmt.x; m_rigidbody.MovePosition( m_rigidbody.position + move * WalkSpeed * Time.deltaTime ); bool isMoving = m_moveAmt.magnitude > 0.1f; animator.SetBool("isWalking", isMoving); } private void Rotating() { if (m_lookAmt.magnitude <= 0.01f) return; if (!m_isHeadThrown) { // NORMAL BODY ROTATION float horizontalRotation = m_lookAmt.x * RotateSpeed * Time.deltaTime; Quaternion deltaRotation = Quaternion.Euler(0, horizontalRotation, 0); m_rigidbody.MoveRotation(m_rigidbody.rotation * deltaRotation); if (CameraTransform != null) { m_verticalRotation -= m_lookAmt.y * RotateSpeed * Time.deltaTime; m_verticalRotation = Mathf.Clamp(m_verticalRotation, -MaxLookAngle, MaxLookAngle); CameraTransform.localRotation = Quaternion.Euler(m_verticalRotation, 0, 0); } } else { // HEAD ROTATION ON GROUND float headRotation = m_lookAmt.x * RotateSpeed * Time.deltaTime; Head.Rotate(0, headRotation, 0); // Add vertical camera rotation when head is on ground if (CameraTransform != null) { m_verticalRotation -= m_lookAmt.y * RotateSpeed * Time.deltaTime; m_verticalRotation = Mathf.Clamp(m_verticalRotation, -MaxLookAngle, MaxLookAngle); CameraTransform.localRotation = Quaternion.Euler(m_verticalRotation, 0, 0); } } } public void Jump() { if (Physics.CheckSphere(GroundCheck.position, GroundCheckRadius, LayerMask.GetMask("Ground"))) { m_rigidbody.AddForce(Vector3.up * JumpForce, ForceMode.Impulse); } } private void ThrowHead() { if (m_isHeadThrown) return; animator.SetTrigger("Throw"); m_isHeadThrown = true; Head.SetParent(null); m_headRigidbody = Head.gameObject.AddComponent(); m_headRigidbody.mass = 1f; m_headRigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ; m_headRigidbody.AddForce(CameraTransform.forward * ThrowForce, ForceMode.Impulse); } private void TryPickupHead() { if (!m_isHeadThrown) return; float distance = Vector3.Distance(transform.position, Head.position); if (distance <= PickupDistance) { PickupHead(); } } private void PickupHead() { m_isHeadThrown = false; // Remove Rigidbody if (m_headRigidbody != null) { Destroy(m_headRigidbody); } // Reattach to player Head.SetParent(transform); // Reset position & rotation Head.localPosition = m_headInitialLocalPos; Head.localRotation = m_headInitialLocalRot; } }