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(); UpdateSFX(); _rb = GetComponent(); _col = GetComponent(); // Учитываем поворот объекта при вычислении смещения 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(); _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(); if (fireScript.enableFire) fireScript.enableFire = false; if (!_rb) _rb = GetComponent(); _rb.linearVelocity = Vector2.zero; } public void OnDeathEnd() { if (!_col) _col = GetComponent(); 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(); 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(); 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(); Vector3 rotatedOffset = transform.rotation * offset; Vector3 spawnPosition = MvpVFXUtility.GetColliderBottomPosition(_col, transform) + rotatedOffset; MvpVFXUtility.Spawn(asset, fallbackResourcePath, spawnPosition, 1f); } } }