Files
HeadlessHazard/Assets/Code/Scripts/Player/PlayerMovement.cs

217 lines
5.8 KiB
C#

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");
// Support both old and new action names without breaking the scene setup.
m_throwAction = map.FindAction("Throw") ?? map.FindAction("Attack");
m_pickupAction = map.FindAction("Pickup") ?? map.FindAction("Interact");
m_rigidbody = GetComponent<Rigidbody>();
animator = GetComponent<Animator>();
}
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 != null ? m_moveAction.ReadValue<Vector2>() : Vector2.zero;
m_lookAmt = m_lookAction != null ? m_lookAction.ReadValue<Vector2>() : Vector2.zero;
if (m_jumpAction != null && m_jumpAction.WasPressedThisFrame())
{
Jump();
}
if (m_throwAction != null && m_throwAction.WasPressedThisFrame())
{
ThrowHead();
}
if (m_pickupAction != null && (m_pickupAction.WasPressedThisFrame() || m_pickupAction.WasPerformedThisFrame()))
{
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<Rigidbody>();
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;
}
}