多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -0,0 +1,14 @@
namespace BaseGames.Enemies.States
{
/// <summary>
/// 受控状态(默认行为)。
/// 敌人处于 AI 正常控制下Behavior Designer 运行中),无特殊 Enter/Exit 动画逻辑。
/// </summary>
public sealed class EnemyControlledState : IEnemyState
{
public EnemyStateType StateType => EnemyStateType.Controlled;
public void Enter(EnemyBase owner) { }
public void Exit(EnemyBase owner) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08377192598a73e43a4037ef1ac3e3c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
namespace BaseGames.Enemies.States
{
/// <summary>
/// 死亡状态。Enter 仅作为扩展点(实际死亡流程由 EnemyBase.Die() 驱动),
/// 防止后续添加死亡特效/逻辑时需要改动 EnemyBase。
/// </summary>
public sealed class EnemyDeadState : IEnemyState
{
public EnemyStateType StateType => EnemyStateType.Dead;
/// <summary>
/// 死亡实际逻辑由 EnemyBase.Die() 处理(禁用碰撞体、播放动画、广播事件)。
/// 此方法保留为扩展点,子类可重写状态字典条目加入自定义逻辑。
/// </summary>
public void Enter(EnemyBase owner) { }
public void Exit(EnemyBase owner) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f0078376e2cfd80419ca7f981c3009ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
namespace BaseGames.Enemies.States
{
/// <summary>
/// 受击状态。播放受击动画,动画结束后自动回到 Controlled。
/// 原 EnemyBase.ForceState 中的 Hurt if-else 逻辑已迁移至此。
/// </summary>
public sealed class EnemyHurtState : IEnemyState
{
public EnemyStateType StateType => EnemyStateType.Hurt;
public void Enter(EnemyBase owner)
{
if (owner.Animancer == null || owner.AnimConfig?.Hurt == null) return;
var animState = owner.Animancer.Play(owner.AnimConfig.Hurt);
animState.Events(owner).OnEnd = () =>
{
// 只在仍处于 Hurt 时才回 Controlled避免 Die 时被覆盖
if (owner.CurrentState == EnemyStateType.Hurt)
owner.ForceState(EnemyStateType.Controlled);
};
}
public void Exit(EnemyBase owner) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2bc4ca8eb93d1aa4e9c3f0be1c726161
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
namespace BaseGames.Enemies.States
{
/// <summary>
/// 僵直状态(霸体耗尽时触发)。
/// 播放 Stagger 动画(若配置),动画结束后自动回到 Controlled。
/// </summary>
public sealed class EnemyStaggerState : IEnemyState
{
public EnemyStateType StateType => EnemyStateType.Stagger;
public void Enter(EnemyBase owner)
{
if (owner.Animancer == null || owner.AnimConfig?.Stagger == null) return;
var animState = owner.Animancer.Play(owner.AnimConfig.Stagger);
animState.Events(owner).OnEnd = () =>
{
if (owner.CurrentState == EnemyStateType.Stagger)
owner.ForceState(EnemyStateType.Controlled);
};
}
public void Exit(EnemyBase owner) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2c296d9aa57cfe49aa907367c99f27f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
namespace BaseGames.Enemies
{
/// <summary>
/// 敌人状态 POCO 接口。
/// EnemyBase.ForceState 通过字典分发 Enter/Exit
/// 枚举 EnemyStateType 保持对外 API 不变。
/// </summary>
public interface IEnemyState
{
/// <summary>对应的枚举值(用于字典键以及 BD 查询)。</summary>
EnemyStateType StateType { get; }
/// <summary>进入此状态时调用。</summary>
void Enter(EnemyBase owner);
/// <summary>离开此状态时调用。</summary>
void Exit(EnemyBase owner);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ebc8841ddc5823844b18be2252b1315b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: