怪物AI-状态模式
1、技术概述
- 使用该技术的情况:在游戏开发中 怪物AI逻辑的实现
- 学习必要性:实现怪物AI逻辑
- 难点:该技术只是将状态模式运用于怪物AI的实现,没有特别的难点
2、技术案例
状态模式
在面向对象系统设计中,经常会遇到依赖于状态的对象。对象的行为会根据状态的改变而改变。
例如:一个怪物(人)对象,在饿的状态:会进入吃人的状态;在暴怒的状态:会进入暴动的状态;
如果一个对象(类)是依赖于状态的,那么程序员在描述改对象的类中,通常会使用许多条件语句来覆盖所有的条件以及 在 这些条件下的对象的行为。
例如: if (monster is 饿) 吃人(); else if (monster is 暴怒) 暴走();
//但是这种方法对于比较复杂的状态判断容易产生错误。
基于大量的条件语句的处理方法有很多不便之处。
首先,增加一个新的状态将会导致对类的大量修改,因此该设计不容易扩展与维护;
另外,状态的转换不明显,也可能发生编程错误。
一个有效的方法就是利用状态模式
状态模式的结构类图如下:

(1)Context:定义了与客户程序的接口,它保持了一个ConcreteState的代表现在状态的实例。 (2)State:定义了状态的接口,它的各个子类封装了在各种不同状态的行为。 (3)ConcreteState子类:封装了在各种不同状态下的行为。
状态模式在实现怪物AI中的例子
例子中,怪物只有两种装填:站立和巡逻:

类图:

(1)FSM:相当于Context类,Finite State Machine的缩写。
属性parameter封装了怪物移动速度、血量、攻击力等数值;
currentState表示当前怪物所处的状态;
states维护了注册到FSM的状态,包括IdleState、ParolState;
transitionState()方法的作用为切换状态。 (2)IState:相当于State接口:
OnEnter()方法在进入状态时执行;
OnUpdate()方法在该状态下时执行;
OnExit()方法在退出该状态时执行。 (3)IdleState和PatrolState:
相当于ConcreteState类,类中的manager表示状态机类FSM。
具体实现:
(1)在FSM类中注册站立状态和巡逻状态,即:将两个状态类的对象添加到states中。
(2)并将当前状态currentState设置为IdleState。
(3)当要切换状态时,状态类会在OnUpdate()方法中利用其属性manager调用FSM类的transitionState()方法,切换状态;
transitionState()方法会利用currentState属性依次调用前一状态的OnExit()方法,和新状态的OnEnter()方法进行初始化。
Ts 代码:
1、首先两个状态类
/** 站立状态*/ export class IdleState implements IState { private manager: FSM = null!; private parameter: Parameter = null!; private timer: number = 0; public constructor(manager: FSM) { this.manager = manager; this.parameter = manager.parameter; } fight(): void { } public onEnter(): void { this.parameter.animator.setValue("走的动作属性", false);//停止走动画 this.parameter.animator.setValue("站立的动作属性", true);//开始站立的动画 } public onExit(): void { this.timer = 0; } public onUpdate(): void { this.timer += Time.deltaTime; if (this.timer >= this.parameter.idleTime) { this.manager.transitionState(StateType.Patrol); } } }
/* 走状态 */ export class PatrolState implements IState { private manager: FSM = null!; private parameter: Parameter = null!; private patrolPosition: number = 0; public constructor(manager: FSM) { this.manager = manager; this.parameter = manager.parameter; } public onEnter(): void { this.parameter.animator.setValue("站立的动作属性", false);//停止站立动画 this.parameter.animator.setValue("走的动作属性", true);//开始走的动画 } public onExit(): void { this.patrolPosition++; if (this.patrolPosition >= this.parameter.patrolPoints.length) { this.patrolPosition = 0; } } public onUpdate(): void { let position = this.parameter.patrolPoints[this.patrolPosition]; tween(this.manager.node).to(this.parameter.moveSpeed * Time.deltaTime, { position: position }); if (math.Vec3.distance(this.manager.node.position, position) < 0.1) { this.manager.transitionState(StateType.Idle); } } }
2、然年状态机 类
/**
* enum StateType
*/
export enum StateType {
//站立
Idle,
//跑路
Patrol
}
/** * Paramater * 怪物包含的参数 */ export interface Parameter { //行走的速度 moveSpeed: number; //站立的时间 idleTime: number; //行走的点 patrolPoints: Vec3[]; //动作控制,这里使用的3D最新的玩偶动画 animator: animation.AnimationController; } /* 怪物的有限状态机FSM */ export default class FSM extends Component { public parameter: Parameter = null!; private currentState: IState = null!; private states: Dictionary<StateType, IState> = new Dictionary<StateType, IState>(); start(): void { this.states.add(StateType.Idle, new IdleState(this)); this.states.add(StateType.Patrol, new PatrolState(this)); this.transitionState(StateType.Idle); } update(): void { this.currentState.onUpdate(); } public transitionState(type: StateType): void { if (this.currentState != null) { this.currentState.onExit(); } this.currentState = this.states.tryGetValue(type); this.currentState.onEnter(); } }
Unity代码:
/* IState接口 */ public interface IState { void OnEnter(); void OnUpdate(); void OnExit(); }
/* 站立状态 */ public class IdleState : IState { private FSM manager; private Parameter parameter; private float timer; public IdleState(FSM manager) { this.manager = manager; this.parameter = manager.parameter; } public void OnEnter() { } public void OnExit() { timer = 0; } public void OnUpdate() { timer += Time.deltaTime; if (timer >= parameter.idleTime) { manager.transitionState(StateType.Patrol); } } }
/* 巡逻状态 */ public class PatrolState : IState { private FSM manager; private Parameter parameter; private int patrolPosition; public PatrolState(FSM manager) { this.manager = manager; this.parameter = manager.parameter; } public void OnEnter() { } public void OnExit() { patrolPosition++; if (patrolPosition >= parameter.patrolPoints.Length) { patrolPosition = 0; } } public void OnUpdate() { manager.transform.position = Vector2.MoveTowards(manager.transform.position, parameter.patrolPoints[patrolPosition].position, parameter.moveSpeed * Time.deltaTime); if (Vector2.Distance(manager.transform.position, parameter.patrolPoints[patrolPosition].position) < 0.1f) { manager.transitionState(BeeStateType.Idle); } } }
/* 状态枚举 */ public enum StateType { Idle,Patrol } /* 怪物包含的参数 */ public class Parameter { public float moveSpeed; public float idleTime; public Transform[] patrolPoints; public Animator animator; } /* 怪物的有限状态机FSM */ public class FSM : MonoBehaviour { public Parameter parameter; private IState currentState; private Dictionary<StateType, IState> states = new Dictionary<StateType, IState>(); void Start() { states.Add(StateType.Idle, new IdleState(this)); states.Add(StateType.Patrol, new PatrolState(this)); transitionState(StateType.Idle); } void Update() { currentState.OnUpdate(); } public void transitionState(StateType type) { if (currentState != null) { currentState.OnExit(); } currentState = states[type]; currentState.OnEnter(); } }

浙公网安备 33010602011771号