Danro/Assets/Resources/Scripts/PlayerController.cs

173 lines
6.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using RR.Game2D.Core;
using UnityEngine;
using UnityEngine.InputSystem;
namespace RR.Game2D.Behaviour
{
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody2D),
typeof(Collider2D),
typeof(Animator))]
public class PlayerController : MonoBehaviour
{
[Header("Управление")]
[SerializeField] private InputActionReference moveAction; // Value(Vector2), например "Move" (A/D, ←/→, stick)
[SerializeField] private InputActionReference jumpAction;
[Header("Горизонтальное движение")]
[SerializeField] private float moveSpeed = 8f;
[SerializeField] private float accel = 40f;
[SerializeField] private float decel = 20f;
[Header("Вертикальное движение")]
[SerializeField] public float jumpVelocity = 50f;
[SerializeField] private float jumpCut = 2f;
[Header("Проверка призмеления")]
[SerializeField] private Transform groundCheck;
[SerializeField] private float groundCheckRadius = 0.05f;
[SerializeField] private LayerMask groundMask;
[Header("Аниматор [Опционально]")]
[SerializeField] private Animator animator; // оставить в инспекторе на всякий случай
[Header("Настройки для уровней")]
[SerializeField] private float deathY = -5f;
private Rigidbody2D rb;
//private Collider2D col;
private float inputX;
private bool jumpPressed, jumpReleased, jumpHold;
private float _fallSpeedYDampingChangeThreshold;
private bool IsGrounded => Grounded();
void OnEnable()
{
moveAction.action.Enable();
jumpAction.action.Enable();
}
void OnDisable()
{
moveAction.action.Disable();
jumpAction.action.Disable();
}
void Awake()
{
rb = GetComponent<Rigidbody2D>();
//col = GetComponent<Collider2D>();
rb.freezeRotation = true;
_fallSpeedYDampingChangeThreshold = CameraManager.instance._fallSpeedYDampingChangeThreshold;
// если не задано в инспекторе — находим автоматически
if (animator == null)
animator = GetComponent<Animator>();
if (animator == null)
animator = GetComponentInChildren<Animator>(true);
if (animator == null)
Debug.LogError($"[{name}] Animator не найден!");
}
void Update()
{
// --- Ввод ---
Vector2 move = moveAction ? moveAction.action.ReadValue<Vector2>() : Vector2.zero;
inputX = Mathf.Abs(move.x) > 0.01f ? Mathf.Sign(move.x) : 0f;
jumpPressed |= jumpAction.action.WasPressedThisFrame();
jumpReleased |= jumpAction.action.WasReleasedThisFrame();
jumpHold |= jumpAction.action.IsPressed();
if (inputX != 0f)
transform.localEulerAngles = Mathf.Sign(inputX) > 0 ? Vector3.zero : new Vector3(0, 180f, 0);
if (rb.linearVelocity.y < _fallSpeedYDampingChangeThreshold && !CameraManager.instance.IsLerpingYDamping && !CameraManager.instance.LerpedFromPlayerFalling)
{
CameraManager.instance.LerpYDamping(true);
}
if (rb.linearVelocity.y >= 0 && !CameraManager.instance.IsLerpingYDamping && CameraManager.instance.LerpedFromPlayerFalling)
{
CameraManager.instance.LerpedFromPlayerFalling = false;
CameraManager.instance.LerpYDamping(false);
}
// --- Анимации ---
animator.SetFloat("Speed", Mathf.Abs(rb.linearVelocity.x));
animator.SetFloat("VSpeed", rb.linearVelocity.y);
animator.SetBool("Grounded", IsGrounded);
}
private void FixedUpdate()
{
// Горизонтальное движение
float target = inputX * moveSpeed;
float rate = (Mathf.Abs(target) > 0.01) ? accel : decel;
float velocityX = Mathf.MoveTowards(rb.linearVelocity.x, target, rate * Time.fixedDeltaTime);
Vector2 newVelocity = rb.linearVelocity;
newVelocity.x = velocityX;
// Вертикальное движение
if ((jumpPressed || jumpHold)&& IsGrounded)
newVelocity.y = jumpVelocity;
if (jumpReleased && newVelocity.y > 0)
newVelocity.y /= Mathf.Max(1f, jumpCut);
rb.linearVelocity = newVelocity;
jumpPressed = jumpReleased = jumpHold = false;
// Смерть
if (transform.position.y < deathY) Die();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Coin"))
{
GameManager.Instance.AddCoin();
Destroy(collision.gameObject);
}
if (collision.CompareTag("Finish"))
{
GameManager.Instance.NextLevel();
}
}
//private void OnDestroy() => Debug.Log("Player destroyed");
/// <summary>
/// Метод для проверки соприкосновения с землей
/// </summary>
/// <returns>bool isGrounded - на земле ли игрок</returns>
bool Grounded()
{
Collider2D hit = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundMask);
bool isGrounded = hit != null
&& hit.CompareTag("Ground");
//&& rb.linearVelocity.y < 0.01f;
animator.SetBool("Jump", !isGrounded);
return isGrounded;
}
/// <summary>
/// Метод смерти персонажа.
/// Базовое поведение - сброс уровня в GameManager
/// </summary>
public void Die()
{
GameManager.Instance.ResetLevel();
}
}
}