ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Unity2D 敌人追逐系统:基于状态枚举的简洁实现

Unity2D 敌人追逐系统:基于状态枚举的简洁实现 1. 引言在 Unity2D 游戏开发中敌人的 AI 行为往往决定了游戏的可玩性与挑战性。本文基于一份简洁的Enemy_Movement.cs代码讲解如何用「状态枚举 触发器检测」的方式实现敌人的待机与追逐行为。这种实现没有复杂的接口和状态类而是通过一个枚举变量和几个关键方法让敌人能够自动感知玩家、切换状态并持续追击非常适合作为入门级敌人 AI 的参考。2. 代码整体结构这份代码的核心思路是用一个EnemyState枚举记录敌人当前状态在Update中根据状态执行对应行为并通过触发器Trigger感知玩家进入或离开从而切换状态。整体结构如下字段声明速度、朝向、状态、刚体、玩家、动画器等。Start 方法获取组件引用并初始化状态为待机。Update 方法在追逐状态下面向玩家并持续移动。触发器方法玩家进入范围时切换为追逐离开时切换回待机。Flip 方法根据玩家位置翻转敌人朝向。ChangeState 方法统一处理状态切换与动画同步。3. 字段与组件声明代码首先声明了敌人所需的各类字段public class Enemy_Movement : MonoBehaviour { public float speed; private int facingDirection -1; // 初始面向方向主要用于控制动画 private EnemyState enemyState; private Rigidbody2D rb; private Transform player; private Animator anim; }其中speed是公开字段可在 Inspector 中调整移动速度facingDirection记录敌人当前面向的方向-1 表示向左1 表示向右用于翻转动画enemyState记录当前状态rb、player、anim分别引用刚体、玩家和动画器组件。4. Start 方法初始化在Start中获取组件引用并将敌人初始状态设为待机void Start() { rb GetComponentRigidbody2D(); anim GetComponentAnimator(); ChangeState(EnemyState.Idle); }这里通过ChangeState而不是直接赋值是为了在进入待机状态时同步播放对应的待机动画。5. Update 方法追逐逻辑在Update中只有当状态为Chasing时才执行追逐逻辑void Update() { if (enemyState EnemyState.Chasing) { if (player.position.x transform.position.x facingDirection -1 || player.position.x transform.position.x facingDirection 1) { Flip(); } Vector2 direction (player.position - transform.position).normalized; rb.velocity direction * speed; } }这段逻辑包含两个关键点朝向翻转当玩家在敌人右侧而敌人面向左facingDirection -1或玩家在左侧而敌人面向右facingDirection 1时调用Flip翻转朝向。持续移动计算敌人指向玩家的方向向量归一化后乘以速度赋值给刚体的velocity实现平滑追击。6. 触发器检测状态切换的开关敌人通过两个触发器方法感知玩家进入或离开范围private void OnTriggerEnter2D(Collider2D collision) { if (collision.gameObject.tag Player) { if (player null) { player collision.transform; } ChangeState(EnemyState.Chasing); } } private void OnTriggerExit2D(Collider2D collision) { if (collision.gameObject.tag Player) { rb.velocity Vector2.zero; ChangeState(EnemyState.Idle); } }当玩家进入敌人的触发器范围时记录玩家引用并切换为追逐当玩家离开时先清零速度再切回待机。这里需要注意触发器需要挂在敌人身上并勾选Is Trigger。玩家对象需要设置Player标签否则无法被识别。玩家离开时清零速度可以避免敌人因惯性继续滑动。7. Flip 方法翻转朝向翻转方法通过反转facingDirection和缩放来实现private void Flip() { facingDirection * -1; transform.localScale new Vector3( transform.localScale.x * -1, transform.localScale.y, transform.localScale.z); }通过将localScale.x取反可以让敌人的 Sprite 在水平方向翻转从而改变面向。同时更新facingDirection保证后续判断不会重复翻转。8. ChangeState 方法状态与动画同步状态切换统一由ChangeState处理并同步动画参数void ChangeState(EnemyState newState) { // 退出当前动画 if (enemyState EnemyState.Idle) anim.SetBool(isIdle, false); else if (enemyState EnemyState.Chasing) anim.SetBool(isChasing, false); enemyState newState; // 更新新的动画 if (enemyState EnemyState.Idle) anim.SetBool(isIdle, true); else if (enemyState EnemyState.Chasing) anim.SetBool(isChasing, true); }这种写法把「退出旧状态」和「进入新状态」的动画处理集中在一个方法里避免在多个地方重复编写动画切换代码。Animator 中需要定义isIdle和isChasing两个 Bool 参数并配置对应的状态转换条件。9. 状态枚举定义最后是状态枚举目前包含待机和追逐两个状态public enum EnemyState { Idle, Chasing, }后续如果需要新增「攻击」「巡逻」等状态只需在枚举中追加成员并在Update和ChangeState中补充对应的分支即可。10. 使用步骤与注意事项要把这份代码应用到你的项目中可以按以下步骤操作在场景中创建敌人对象挂载Enemy_Movement脚本。为敌人添加Rigidbody2D组件并将Body Type设为Dynamic。添加一个Box Collider 2D作为触发器勾选Is Trigger并调整大小作为敌人的感知范围。为敌人添加Animator组件并创建包含isIdle、isChasing参数的动画控制器。确保玩家对象带有Player标签。在动画编辑器中节点的使用各自通过状态独自控制这样可以确保当我们想要增添更多怪物行为动画都不会混乱使用过程中还需要注意以下几点触发器范围感知范围由触发器 Collider 的大小决定而不是代码中的数值调整时直接修改 Collider 即可。刚体约束建议在 Rigidbody2D 的 Constraints 中锁定 Z 轴旋转避免敌人追击时发生旋转。空引用保护如果玩家可能在游戏中被销毁建议在Update中增加player null的判断避免空指针异常。动画参数匹配Animator 中的参数名必须与代码中的isIdle、isChasing完全一致否则动画无法正确切换。11. 总结这份Enemy_Movement.cs通过「状态枚举 触发器检测」的方式用较少的代码实现了敌人的待机与追逐行为。相比复杂的接口状态机这种实现更直观、更易上手适合状态数量较少的敌人 AI。它的核心在于用枚举记录状态、在 Update 中按状态执行行为、用触发器感知玩家并切换状态、通过 ChangeState 统一同步动画。理解了这几个要点你就能在此基础上扩展出攻击、巡逻等更丰富的敌人行为。
返回列表