129 lines
3.9 KiB
C#
129 lines
3.9 KiB
C#
using System;
|
|
using KBCore.Refs;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
namespace Infrastructure.Unity
|
|
{
|
|
[RequireComponent(typeof(Rigidbody))]
|
|
public class PlayerController : MonoBehaviour
|
|
{
|
|
[Header("Movement Settings")]
|
|
[SerializeField]
|
|
private float moveSpeed = 8f;
|
|
[SerializeField] private float maxVelocityChange = 10f;
|
|
[SerializeField] private float snapForce = 15f;
|
|
|
|
[Header("Interaction")]
|
|
[SerializeField] private LayerMask tileLayer;
|
|
[SerializeField] private float groundCheckDistance = 1.5f;
|
|
|
|
[Self] [SerializeField] private Rigidbody rb;
|
|
|
|
private InputSystem_Actions _actions;
|
|
private Vector2 _moveInput;
|
|
|
|
public Rigidbody Rigidbody => rb;
|
|
|
|
private void OnEnable()
|
|
{
|
|
_actions.Player.Enable();
|
|
|
|
_actions.Player.Move.performed += OnMovePerformed;
|
|
_actions.Player.Move.canceled += OnMoveCanceled;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
_actions.Player.Move.performed -= OnMovePerformed;
|
|
_actions.Player.Move.canceled -= OnMoveCanceled;
|
|
|
|
_actions.Player.Disable();
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
_actions = new InputSystem_Actions();
|
|
|
|
rb.freezeRotation = true;
|
|
rb.useGravity = true;
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
HandleMovement();
|
|
DetectGround();
|
|
}
|
|
|
|
private void HandleMovement()
|
|
{
|
|
var targetVelocity = Vector3.zero;
|
|
var snapAxis = Vector3.zero;
|
|
|
|
if (_moveInput.sqrMagnitude > 0.1f)
|
|
{
|
|
if (Mathf.Abs(_moveInput.x) > Mathf.Abs(_moveInput.y))
|
|
{
|
|
targetVelocity = new Vector3(_moveInput.x > 0 ? moveSpeed : -moveSpeed, 0, 0);
|
|
snapAxis = Vector3.forward;
|
|
}
|
|
else
|
|
{
|
|
targetVelocity = new Vector3(0, 0, _moveInput.y > 0 ? moveSpeed : -moveSpeed);
|
|
snapAxis = Vector3.right;
|
|
}
|
|
}
|
|
|
|
var velocity = rb.linearVelocity;
|
|
var velocityChange = (targetVelocity - velocity);
|
|
|
|
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
|
|
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
|
|
velocityChange.y = 0f;
|
|
|
|
rb.AddForce(velocityChange, ForceMode.VelocityChange);
|
|
|
|
if (snapAxis != Vector3.zero)
|
|
{
|
|
ApplySnapping(snapAxis);
|
|
}
|
|
else
|
|
{
|
|
ApplySnapping(Vector3.right);
|
|
ApplySnapping(Vector3.forward);
|
|
}
|
|
}
|
|
|
|
private void ApplySnapping(Vector3 axis)
|
|
{
|
|
var currentPos = Vector3.Dot(transform.position, axis);
|
|
var targetPos = Mathf.Round(currentPos);
|
|
|
|
var diff = targetPos - currentPos;
|
|
|
|
var correction = axis * (diff * snapForce);
|
|
rb.AddForce(correction, ForceMode.Acceleration);
|
|
}
|
|
|
|
private void DetectGround()
|
|
{
|
|
if (Physics.Raycast(transform.position, Vector3.down, out var hit, groundCheckDistance, tileLayer))
|
|
{
|
|
if (hit.collider.TryGetComponent<TileViewAdapter>(out var tileAdapter))
|
|
{
|
|
tileAdapter.OnPlayerStep();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnMovePerformed(InputAction.CallbackContext ctx)
|
|
{
|
|
_moveInput = ctx.ReadValue<Vector2>();
|
|
}
|
|
|
|
private void OnMoveCanceled(InputAction.CallbackContext ctx)
|
|
{
|
|
_moveInput = Vector2.zero;
|
|
}
|
|
}
|
|
} |