// Assets/Scripts/Player/States/SwimState.cs
// 游泳状态:玩家在液体中时使用(Architecture 21_LiquidPuzzleModule §5)
// ⚠️ 遵循 PlayerStateBase 构造函数注入模式(非 MonoBehaviour)
// ⚠️ 输入通过 Input.MoveInput / Input.JumpStartedEvent 访问(项目实际 API)
using BaseGames.Player;
using BaseGames.World.Liquid;
using UnityEngine;
namespace BaseGames.Player.States
{
///
/// 游泳状态:玩家在液体中时使用。
/// 需要 AbilityType.Swim 已解锁;若未解锁则由 WaterDangerState 触发溺水流程。
/// 由 PlayerController 在收到 EVT_LiquidEntered 后切换进入。
///
public class SwimState : PlayerStateBase
{
private LiquidPhysicsConfigSO _currentPhysics;
private float _originalGravity;
public SwimState(PlayerController owner) : base(owner) { }
/// 由 PlayerController 在切换状态前调用,注入当前液体区域的物理配置。
public void SetPhysicsConfig(LiquidPhysicsConfigSO config) => _currentPhysics = config;
public override void OnStateEnter()
{
_originalGravity = Move.Rb.gravityScale;
Move.SetGravityScale(_currentPhysics?.GravityScale ?? 0.3f);
if (AnimCfg?.SwimIdle != null)
Anim?.Play(AnimCfg.SwimIdle);
Input.JumpStartedEvent += OnJumpStarted;
}
public override void OnStateExit()
{
Input.JumpStartedEvent -= OnJumpStarted;
Move.SetGravityScale(_originalGravity);
}
public override void OnStateUpdate()
{
var input = Input.MoveInput;
var maxSpeed = _currentPhysics?.MaxSwimSpeed ?? 4f;
var accel = _currentPhysics?.SwimAcceleration ?? 8f;
var drag = _currentPhysics?.DragCoefficient ?? 3f;
var rb = Move.Rb;
if (input != Vector2.zero)
{
var targetVel = input * maxSpeed;
rb.velocity = Vector2.MoveTowards(rb.velocity, targetVel, accel * Time.deltaTime);
if (AnimCfg?.SwimMove != null)
Anim?.Play(AnimCfg.SwimMove);
}
else
{
// 水下浮力(持续向上的微弱力)
rb.AddForce(Vector2.up * (_currentPhysics?.BuoyancyForce ?? 0.5f), ForceMode2D.Force);
if (AnimCfg?.SwimIdle != null)
Anim?.Play(AnimCfg.SwimIdle);
}
// 施加水阻
rb.velocity *= 1f - drag * Time.deltaTime;
}
public override PlayerStateBase GetNextState()
{
// 离开液体区域由 PlayerController 订阅 EVT_LiquidExited 后切换到 FallState
return null;
}
private void OnJumpStarted()
{
// 跳跃键 = 跃出水面冲量
Move.Rb.AddForce(Vector2.up * (_currentPhysics?.SurfaceExitSpeed ?? 5f),
ForceMode2D.Impulse);
}
}
}