135 lines
4.2 KiB
C#
135 lines
4.2 KiB
C#
using System;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
|
|
namespace OnlyScove.Scripts
|
|
{
|
|
public class PlayerController : MonoBehaviour
|
|
{
|
|
private static readonly int MoveAmount = Animator.StringToHash("moveAmount");
|
|
|
|
[SerializeField] private InputReader inputReader;
|
|
[SerializeField] private float rotationSpeed = 500f;
|
|
[SerializeField] private float moveSpeed = 10f;
|
|
[SerializeField] private float jumpHeight = 2f;
|
|
[SerializeField] private float animationDamping = 0.2f;
|
|
[SerializeField] private float groundCheckRadius = 0.2f;
|
|
[SerializeField] private Vector3 groundCheckOffset;
|
|
[SerializeField] private LayerMask groundMask;
|
|
|
|
CameraController cameraController;
|
|
Animator animator;
|
|
private CharacterController characterController;
|
|
|
|
Quaternion targetRotation;
|
|
private float horizontal;
|
|
private float vertical;
|
|
bool isGrounded;
|
|
private bool wasGrounded;
|
|
private bool hasControl = true;
|
|
private float ySpeed;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Camera.main != null) cameraController = Camera.main.GetComponent<CameraController>();
|
|
animator = GetComponent<Animator>();
|
|
characterController = GetComponent<CharacterController>();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
inputReader.OnJumpEvent += HandleJump;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
inputReader.OnJumpEvent -= HandleJump;
|
|
}
|
|
|
|
private void HandleJump()
|
|
{
|
|
if (isGrounded && hasControl)
|
|
{
|
|
// Công thức tính vận tốc nhảy: v = sqrt(h * -2 * g)
|
|
ySpeed = Mathf.Sqrt(jumpHeight * -2f * Physics.gravity.y);
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
horizontal = inputReader.MoveInput.x;
|
|
vertical = inputReader.MoveInput.y;
|
|
float moveAmount = Mathf.Clamp01(Math.Abs(horizontal) + Math.Abs(vertical));
|
|
|
|
var moveInput = (new Vector3(horizontal, 0, vertical)).normalized;
|
|
|
|
var moveDirection = cameraController.PlanarRotation * moveInput;
|
|
|
|
if (!hasControl)
|
|
return;
|
|
|
|
wasGrounded = isGrounded;
|
|
GroundCheck();
|
|
|
|
// Phát hiện tiếp đất (Landing)
|
|
if (isGrounded && !wasGrounded && ySpeed < -1f)
|
|
{
|
|
// Rung camera khi tiếp đất mạnh
|
|
if (cameraController != null)
|
|
{
|
|
cameraController.Shake(0.2f, 0.15f);
|
|
}
|
|
}
|
|
|
|
if (isGrounded && ySpeed < 0)
|
|
{
|
|
ySpeed = -2f; // Giữ nhân vật dính xuống mặt đất
|
|
}
|
|
else
|
|
{
|
|
ySpeed += Physics.gravity.y * Time.deltaTime;
|
|
}
|
|
|
|
var velocity = moveDirection * moveSpeed;
|
|
velocity.y = ySpeed;
|
|
|
|
characterController.Move(velocity * Time.deltaTime);
|
|
|
|
if (moveAmount > 0)
|
|
{
|
|
targetRotation = Quaternion.LookRotation(moveDirection);
|
|
|
|
}
|
|
|
|
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation,
|
|
Time.deltaTime * rotationSpeed);
|
|
|
|
animator.SetFloat(MoveAmount, moveAmount, animationDamping, Time.deltaTime);
|
|
}
|
|
|
|
void GroundCheck()
|
|
{
|
|
isGrounded =
|
|
Physics.CheckSphere(transform.TransformPoint(groundCheckOffset), groundCheckRadius, groundMask);
|
|
}
|
|
|
|
public void SetControl(bool control)
|
|
{
|
|
this.hasControl = control;
|
|
characterController.enabled = hasControl;
|
|
|
|
if (!hasControl)
|
|
{
|
|
animator.SetFloat(MoveAmount, 0f);
|
|
targetRotation = transform.rotation;
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
Gizmos.color = new Color(0, 1, 0, 0.5f);
|
|
Gizmos.DrawSphere(transform.TransformPoint(groundCheckOffset), groundCheckRadius);
|
|
}
|
|
}
|
|
}
|