Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Интегрирована система кастомных визуальных эффектов (VFX): - Добавлена новая утилита MvpVFXUtility и настройки MvpVFXSpawnSettings для спавна эффектов. - Реализован пул эффектов VFXPool с поддержкой отслеживания версий спавна, сброса оверрайдов и анимации масштаба по времени. - Добавлены эффекты прыжка и приземления в PlayerAnimationEvents. - Интегрирован эффект DeathVignetteController для плавного затемнения экрана при смерти игрока. - Добавлены частицы stompImpactVFX при уничтожении врагов прыжком сверху (EnemyController). - Реализован эффект конфетти finishVFX при успешном завершении уровня (LevelFinish). - Интегрированы эффекты искр при сборе монеток, кристаллов и других собираемых предметов (Collectible, EnvironmentalCollectibleBase). - Улучшен и визуально доработан пользовательский интерфейс (UI): - Добавлен скрипт QRCodeTierHighlight для цветовой подсветки QR-кодов в зависимости от тира приза. - Реализована пульсация блока приза в баннере победы (WinBannerController). - Обновлено обозначение валюты в BalanceDisplay с "₽" на "руб.". - Добавлены новые префабы, сцены, ассеты тайлсетов и шейдеров для настройки визуального стиля. - Обновлён протокол и инициализация подсветки COM-платы: - Изменен префикс команд подсветки с 85/86 на 8550, а диапазон эффектов обновлен с 40...52 на 10...22 (LightController, LightMode, LightCycleDurations). - Исправлена хардкод-команда сброса подсветки при инициализации в ComDeviceClient с устаревшей 8600 на новую 8550 для предотвращения рассинхронизации буфера обмена платы.
167 lines
6.3 KiB
C#
167 lines
6.3 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) VFXPool.Instance.Spawn(deathVFX, _deathVFXSpawnPoint, 1f);
|
|
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);
|
|
}
|
|
}
|
|
}
|