Danro/Assets/Scripts/Behaviour/Controllers/PlayerController.cs
Danil Iarosh 5bafc385da feat(audio): increase SFX pool size and preload audio data
- Increased SFX pool size from 8 to 16 in AudioManager
- Enabled preloadAudioData for multiple SFX files
- Removed unused VisualScripting import from Checkpoint script
- Reordered using statements in several scripts for consistency
- Added CoinCollectible component to Coin prefab with pickup effects
- Updated sorting layers and mesh LOD settings in Coin prefabs
- Fixed typo in Interfaces.cs: optionaAttachPoint to optionalAttachPoint
- Modified AddCoin method to accept count parameter and handle coin overflow
- Moved projectile scripts (BasicProjectile, EnemyBasicProjectile, PhysicsProjectile, PickableProjectile)
- Cleaned up unused namespaces and imports across various scripts
2025-10-30 16:39:15 +03:00

211 lines
7.5 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 UnityEngine;
using UnityEngine.InputSystem;
using RR.Common.Interfaces;
using RR.Game2D.Core.Managers;
using RR.Game2D.Behaviour.Camera;
using RR.Game2D.Behaviour.ScriptableObjects;
namespace RR.Game2D.Behaviour
{
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody2D),
typeof(Collider2D),
typeof(Animator))]
public class PlayerController : MonoBehaviour, IDamageable
{
[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;
public bool IsGrounded => Grounded();
[Header("Проверка призмеления")]
[SerializeField] private Transform groundCheck;
[SerializeField] private float groundCheckRadius = 0.05f;
[SerializeField] private LayerMask groundMask;
[Header("Аниматор [Опционально]")]
[SerializeField] private Animator animator; // оставить в инспекторе на всякий случай
[Header("Здоровье")]
[SerializeField] private int maxHealth = 3;
private Health _health;
public float CurrentHealth => _health?.CurrentHealth ?? 0;
public float MaxHealth => _health?.MaxHealth ?? 0;
[Header("FX")]
[SerializeField] public SFXAsset stepSounds;
[SerializeField] public SFXAsset hurtSounds;
[SerializeField] public SFXAsset jumpSounds;
private Rigidbody2D rb;
// private Collider2D col;
private float _inputX;
private bool _jumpPressed, _jumpReleased, _jumpHold;
private float _fallSpeedYDampingChangeThreshold;
// Аниматор
private static readonly int Jump = Animator.StringToHash("Jump");
private static readonly int Speed = Animator.StringToHash("Speed");
private static readonly int VSpeed = Animator.StringToHash("VSpeed");
private static readonly int GroundedAnimator = Animator.StringToHash("Grounded");
private static readonly int Death = Animator.StringToHash("Death");
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 не найден!");
_health = GetComponent<Health>();
if (_health == null)
{
_health = gameObject.AddComponent<Health>();
}
_health.ResetHealth();
_health.SetOwner(this);
_health.SetMaxHealth(maxHealth);
}
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(GroundedAnimator, 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();
}
if (collision.CompareTag("Enemy"))
{
TakeDamage(1f);
}
}
public void TakeDamage(float amount)
{
_health.TakeDamage(amount);
}
public void Heal(float amount)
{
_health.Heal(amount);
}
public void Die()
{
gameObject.layer = LayerMask.NameToLayer("No Collision");
rb.constraints = RigidbodyConstraints2D.FreezeAll;
animator.SetTrigger(Death);
}
/// <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;
}
}
}