多轮审查和修复
This commit is contained in:
149
Assets/Scripts/Animation/PlayerAnimationEvents.cs
Normal file
149
Assets/Scripts/Animation/PlayerAnimationEvents.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using Animancer;
|
||||
using BaseGames.Combat;
|
||||
using BaseGames.Feedback;
|
||||
using BaseGames.Parry;
|
||||
using BaseGames.Player;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Animation
|
||||
{
|
||||
/// <summary>
|
||||
/// 玩家动画事件接收器(架构 §AnimationModule)。
|
||||
/// 挂载于玩家 Prefab 根节点。负责将 Animancer 动画时间点回调路由到
|
||||
/// HitBox 激活、招架窗口、无敌帧、移动取消窗口、反馈等系统。
|
||||
///
|
||||
/// 使用方式:
|
||||
/// 1. 在 Inspector 中填充 _hitBoxes、_hurtBox、_mover、_parrySystem。
|
||||
/// 2. 将每条 ClipTransition + AnimationEventConfigSO 配对添加到 _bindings。
|
||||
/// 3. Awake 中 AnimationEventBinder.Bind 自动完成注入。
|
||||
/// </summary>
|
||||
public class PlayerAnimationEvents : MonoBehaviour, IAnimationEventHandler
|
||||
{
|
||||
[Serializable]
|
||||
public struct EventBinding
|
||||
{
|
||||
[Tooltip("Animancer ClipTransition(需与动画组件中同一引用绑定)。")]
|
||||
public ClipTransition clip;
|
||||
|
||||
[Tooltip("对应的 AnimationEventConfigSO 资产。")]
|
||||
public AnimationEventConfigSO config;
|
||||
}
|
||||
|
||||
[Header("子系统引用")]
|
||||
[SerializeField] private HitBox[] _hitBoxes;
|
||||
[SerializeField] private HurtBox _hurtBox;
|
||||
[SerializeField] private PlayerMovement _mover;
|
||||
[SerializeField] private ParrySystem _parrySystem;
|
||||
|
||||
[Header("事件绑定(每个 Clip 对应一个配置资产)")]
|
||||
[SerializeField] private EventBinding[] _bindings;
|
||||
|
||||
private IFeedbackPlayer _feedback;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// IFeedbackPlayer 由父层或同层实现(PlayerFeedback / NullFeedbackPlayer)
|
||||
_feedback = GetComponentInParent<IFeedbackPlayer>()
|
||||
?? NullFeedbackPlayer.Instance;
|
||||
|
||||
foreach (var b in _bindings)
|
||||
AnimationEventBinder.Bind(b.clip, b.config, this);
|
||||
}
|
||||
|
||||
// ── IAnimationEventHandler ─────────────────────────────────────────
|
||||
|
||||
public void HandleEvent(AnimationEventType type, string payload)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
// ── 命中判定 ──────────────────────────────────────────────
|
||||
case AnimationEventType.EnableHitBox:
|
||||
SetHitBoxActive(payload, true);
|
||||
break;
|
||||
|
||||
case AnimationEventType.DisableHitBox:
|
||||
SetHitBoxActive(payload, false);
|
||||
break;
|
||||
|
||||
case AnimationEventType.AttackImpact:
|
||||
_feedback.PlayAttackWhoosh();
|
||||
break;
|
||||
|
||||
// ── 招架窗口 ──────────────────────────────────────────────
|
||||
case AnimationEventType.EnableParryWindow:
|
||||
_parrySystem?.OpenParryWindow();
|
||||
break;
|
||||
|
||||
case AnimationEventType.DisableParryWindow:
|
||||
_parrySystem?.CloseParryWindow();
|
||||
break;
|
||||
|
||||
// ── 无敌帧 ────────────────────────────────────────────────
|
||||
case AnimationEventType.EnableIFrame:
|
||||
_hurtBox?.SetInvincible(true);
|
||||
break;
|
||||
|
||||
case AnimationEventType.DisableIFrame:
|
||||
_hurtBox?.SetInvincible(false);
|
||||
break;
|
||||
|
||||
// ── 移动反馈 ──────────────────────────────────────────────
|
||||
case AnimationEventType.LandImpact:
|
||||
_feedback.PlayLandImpact();
|
||||
break;
|
||||
|
||||
case AnimationEventType.JumpLaunch:
|
||||
_feedback.PlayJumpLaunch();
|
||||
break;
|
||||
|
||||
case AnimationEventType.Footstep:
|
||||
_feedback.PlayFootstep();
|
||||
break;
|
||||
|
||||
// ── 取消窗口 ──────────────────────────────────────────────
|
||||
case AnimationEventType.CancelWindowOpen:
|
||||
_mover?.SetCancelWindowOpen(true);
|
||||
break;
|
||||
|
||||
case AnimationEventType.CancelWindowClose:
|
||||
_mover?.SetCancelWindowOpen(false);
|
||||
break;
|
||||
|
||||
// ── 通用反馈 ──────────────────────────────────────────────
|
||||
case AnimationEventType.TriggerFeedback:
|
||||
if (!string.IsNullOrEmpty(payload))
|
||||
_feedback.TriggerPreset(payload);
|
||||
break;
|
||||
|
||||
case AnimationEventType.PlaySFX:
|
||||
if (!string.IsNullOrEmpty(payload))
|
||||
_feedback.PlaySFXById(payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ── 私有辅助 ───────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// 按 Id 激活或停用 HitBox。
|
||||
/// payload 为空时操作所有 HitBox;非空时仅操作 Id 匹配的 HitBox。
|
||||
/// </summary>
|
||||
private void SetHitBoxActive(string id, bool active)
|
||||
{
|
||||
if (_hitBoxes == null) return;
|
||||
|
||||
bool matchAll = string.IsNullOrEmpty(id);
|
||||
|
||||
foreach (var hb in _hitBoxes)
|
||||
{
|
||||
if (hb == null) continue;
|
||||
if (matchAll || hb.Id == id)
|
||||
{
|
||||
if (active) hb.Activate();
|
||||
else hb.Deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user