using UnityEngine;
namespace BaseGames.Input
{
///
/// 帧级输入缓冲。持续 _bufferDuration 秒,允许玩家提前输入跳跃/攻击/冲刺。
/// 须与 PlayerController 在同一 GameObject 上。
///
public class InputBuffer : MonoBehaviour
{
// _inputReader 由 PlayerController.Awake 注入,无需在 Inspector 单独配置。
private InputReaderSO _inputReader;
[SerializeField] private float _jumpBufferDuration = 0.15f;
[SerializeField] private float _attackBufferDuration = 0.12f;
[SerializeField] private float _dashBufferDuration = 0.10f;
private float _jumpBuffer;
private float _attackBuffer;
private float _dashBuffer;
#if UNITY_EDITOR
// ── 运行时调试(Inspector 中可见)───────────────────────────────
[Header("\u2500\u2500 \u8fd0\u884c\u65f6\u8c03\u8bd5 \u2500\u2500")]
[SerializeField] private float _dbg_JumpBuffer;
[SerializeField] private float _dbg_AttackBuffer;
[SerializeField] private float _dbg_DashBuffer;
#endif
// ── Named handlers to allow proper unsubscription ─────────────────────
private void HandleJumpStarted() => _jumpBuffer = _jumpBufferDuration;
private void HandleAttackStarted() => _attackBuffer = _attackBufferDuration;
private void HandleDashStarted() => _dashBuffer = _dashBufferDuration;
/// 由 PlayerController 在 Awake 中注入 InputReader,无需在 Inspector 单独指定。
public void Init(InputReaderSO reader)
{
_inputReader = reader;
}
private void OnEnable()
{
if (_inputReader == null) return;
_inputReader.JumpStartedEvent += HandleJumpStarted;
_inputReader.AttackEvent += HandleAttackStarted;
_inputReader.DashEvent += HandleDashStarted;
}
private void OnDisable()
{
if (_inputReader == null) return;
_inputReader.JumpStartedEvent -= HandleJumpStarted;
_inputReader.AttackEvent -= HandleAttackStarted;
_inputReader.DashEvent -= HandleDashStarted;
}
private void Update()
{
float dt = Time.deltaTime;
_jumpBuffer = Mathf.Max(0f, _jumpBuffer - dt);
_attackBuffer = Mathf.Max(0f, _attackBuffer - dt);
_dashBuffer = Mathf.Max(0f, _dashBuffer - dt);
#if UNITY_EDITOR
_dbg_JumpBuffer = _jumpBuffer;
_dbg_AttackBuffer = _attackBuffer;
_dbg_DashBuffer = _dashBuffer;
#endif
}
/// 消耗跳跃缓冲(读取并清空)。
public bool ConsumeJump()
{
if (_jumpBuffer <= 0f) return false;
_jumpBuffer = 0f;
return true;
}
/// 消耗攻击缓冲(读取并清空)。
public bool ConsumeAttack()
{
if (_attackBuffer <= 0f) return false;
_attackBuffer = 0f;
return true;
}
/// 消耗冲刺缓冲(读取并清空)。
public bool ConsumeDash()
{
if (_dashBuffer <= 0f) return false;
_dashBuffer = 0f;
return true;
}
}
}