Danro/Assets/Scripts/Animations/PlayerAnimationEvents.cs
Danil Iarosh 53afa5498e
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Fix player bouncing off corners and align collider
- Исправлено поведение игрока при падении с высоты и разворотах (устранен сильный отскок от углов)
- Центрирован PolygonCollider2D по оси X на префабе character_defeat_4.prefab (m_Offset.x установлен в 0)
- Упрощена форма PolygonCollider2D до симметричного выпуклого шестиугольника
- Сохранен бэкап старого префаба игрока в Player_Old.prefab
2026-07-16 15:39:43 +03:00

176 lines
6.6 KiB
C#

using UnityEngine;
using RR.Common.Audio;
using RR.Game2D.Core.Managers;
using RR.Game2D.Behaviour;
using RR.Game2D.Behaviour.ScriptableObjects;
using RR.Game2D.FX;
using RR.Common.UI;
using UnityEngine.VFX;
namespace RR.Game2D.Animations
{
public class PlayerAnimationEvents : MonoBehaviour, CreatureAnimationEvents
{
// --- VFX Assets ---
[SerializeField] private VisualEffectAsset deathVFX;
[SerializeField] private Vector3 deathVFXOffset = Vector3.zero;
[SerializeField] private VisualEffectAsset runVFX;
[SerializeField] private Vector3 runVFXOffset = Vector3.zero;
[SerializeField] private VisualEffectAsset jumpVFX;
[SerializeField] private string jumpVFXResourcePath = "VFX/MVP_Dirt_VFX";
[SerializeField] private Vector3 jumpVFXOffset = Vector3.zero;
[SerializeField] private VisualEffectAsset landingVFX;
[SerializeField] private string landingVFXResourcePath = "VFX/MVP_Dirt_VFX";
[SerializeField] private Vector3 landingVFXOffset = Vector3.zero;
[SerializeField] private float landingMinFallSpeed = 1f;
// --- Private Fields ---
// SFX Assets
private SFXAsset _stepSounds;
private SFXAsset _hurtSounds;
private SFXAsset _jumpSounds;
// Components
private Rigidbody2D _rb;
private Collider2D _col;
private PlayerController _controller;
// VFX Spawn Points
private Vector3 _deathVFXSpawnPoint;
private Vector3 _runVFXSpawnPoint;
private bool _wasGrounded;
private bool _groundedStateInitialized;
private float _lastVerticalVelocity;
private void OnEnable() => LevelPlayerSFX.Instance.SFXChanged += UpdateSFX;
private void OnDisable() => LevelPlayerSFX.Instance.SFXChanged -= UpdateSFX;
private void Awake()
{
_controller = GetComponent<PlayerController>();
UpdateSFX();
_rb = GetComponent<Rigidbody2D>();
_col = GetComponent<Collider2D>();
// Учитываем поворот объекта при вычислении смещения
Vector3 deathRotatedOffset = transform.rotation * deathVFXOffset;
Vector3 runRotatedOffset = transform.rotation * runVFXOffset;
_deathVFXSpawnPoint = (_col ? _col.bounds.center : transform.position) + deathRotatedOffset;
_runVFXSpawnPoint = (_col ? _col.bounds.center : transform.position) + runRotatedOffset;
_wasGrounded = _controller != null && _controller.IsGrounded;
_groundedStateInitialized = true;
_lastVerticalVelocity = _rb ? _rb.linearVelocity.y : 0f;
}
private void Update()
{
if (_controller == null) return;
bool isGrounded = _controller.IsGrounded;
if (!_groundedStateInitialized)
{
_wasGrounded = isGrounded;
_groundedStateInitialized = true;
}
if (!_wasGrounded && isGrounded && _lastVerticalVelocity <= -landingMinFallSpeed)
{
SpawnGroundVFX(landingVFX, landingVFXResourcePath, landingVFXOffset);
}
_wasGrounded = isGrounded;
if (_rb) _lastVerticalVelocity = _rb.linearVelocity.y;
}
public void UpdateSFX()
{
PlayerController controller = GetComponent<PlayerController>();
_stepSounds = controller.stepSounds;
_hurtSounds = controller.hurtSounds;
_jumpSounds = controller.jumpSounds;
}
public void OnDeath() {}
public void OnDeathBegin()
{
DeathVignetteController.Instance.Show();
if (_hurtSounds && _hurtSounds.soundEffects.Length > 0)
GameManager.Instance.Audio.PlayRandomSfxAt(_hurtSounds.soundEffects, transform.position);
PlayerFireScript fireScript = GetComponent<PlayerFireScript>();
if (fireScript.enableFire) fireScript.enableFire = false;
if (!_rb) _rb = GetComponent<Rigidbody2D>();
_rb.linearVelocity = Vector2.zero;
}
public void OnDeathEnd()
{
if (!_col) _col = GetComponent<Collider2D>();
Vector3 rotatedOffset = transform.rotation * deathVFXOffset;
_deathVFXSpawnPoint = _col ? _col.bounds.center : transform.position + rotatedOffset;
if (deathVFX)
{
MvpVFXSpawnSettings spawnSettings = new MvpVFXSpawnSettings
{
useScale3D = true,
scale3D = (_col ? _col.bounds.size : Vector3.one) * 0.5f,
rotation = transform.rotation
};
MvpVFXUtility.Spawn(deathVFX, null, _deathVFXSpawnPoint, 1f, spawnSettings);
}
gameObject.layer = LayerMask.NameToLayer("Default");
// _rb.constraints = RigidbodyConstraints2D.FreezeRotation;
_controller.isDeadAtMoment = false;
PlayerFireScript fireScript = GetComponent<PlayerFireScript>();
if (!fireScript.enableFire) fireScript.enableFire = true;
GameManager.Instance.RespawnPlayer();
DeathVignetteController.Instance.Hide();
}
public void OnStep()
{
if (_stepSounds && _stepSounds.soundEffects.Length > 0)
GameManager.Instance.Audio.PlayRandomSfxAt(_stepSounds.soundEffects, transform.position);
if (!_col) _col = GetComponent<Collider2D>();
Vector3 rotatedOffset = transform.rotation * runVFXOffset;
_runVFXSpawnPoint = _col ? _col.bounds.center : transform.position + rotatedOffset;
if (runVFX) VFXPool.Instance.Spawn(runVFX, _runVFXSpawnPoint, 1f);
}
public void OnJump()
{
if (_jumpSounds && _jumpSounds.soundEffects.Length > 0)
GameManager.Instance.Audio.PlayRandomSfxAt(_jumpSounds.soundEffects, transform.position);
SpawnGroundVFX(jumpVFX, jumpVFXResourcePath, jumpVFXOffset);
}
private void SpawnGroundVFX(VisualEffectAsset asset, string fallbackResourcePath, Vector3 offset)
{
if (!_col) _col = GetComponent<Collider2D>();
Vector3 rotatedOffset = transform.rotation * offset;
Vector3 spawnPosition = MvpVFXUtility.GetColliderBottomPosition(_col, transform) + rotatedOffset;
MvpVFXUtility.Spawn(asset, fallbackResourcePath, spawnPosition, 1f);
}
}
}