在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
命令模式:游戏开发设计模式之命令模式(unity3d 示例实现) 对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现) 原型模式:游戏开发设计模式之原型模式 & unity3d JSON的使用(unity3d 示例实现)
说
起状态模式游戏开发者们第一个想到的一定是AI的有限状态机FSMs,状态模式确实是实现有限状态机的一种方法。之后还会讲状态机的进阶分层状态机
(hierarchical state machines),和pushdown自动机(pushdown automata),
本文就拿人物控制的有限状态机来讲讲状态机模式,本文例子其实是状态模式和观察者模式的组合,通过获取玩家按键消息来改变状态。
如果想要你实现一个2d或3d游戏中的人物控制(本文拿2d游戏举例),可以让人物走、跑,相信不少人会这么写: if (Input.GetKey(KeyCode.D)) { …设置方向向右.. if (Input.GetKey(KeyCode.LeftShift)) { ..移动..播放跑步动画.. } else { ..移动..播放走路动画.. } } else if (Input.GetKey(KeyCode.A)) { …设置方向向左.. if (Input.GetKey(KeyCode.LeftShift)) { ..移动..播放跑步动画.. } else { ..移动..播放走路动画.. } }
bool isJump = false; if (Input.GetKeyDown(KeyCode.W)) { isJump = true; } if (Input.GetKey(KeyCode.D)) { …设置方向向右.. if (Input.GetKey(KeyCode.LeftShift)) { if(!isJump) ..移动..播放跑步动画.. else ..移动..播放跳跃动画.. } else { if(!isJump) ..移动..播放走路动画.. else ..移动..播放跳跃动画.. } } else if (Input.GetKey(KeyCode.A)) { …设置方向向左.. if(!isJump) ..移动..播放跑步动画.. else ..移动..播放跳跃动画.. } else { if(!isJump) ..移动..播放走路动画.. else ..移动..播放跳跃动画.. } }
bool isCrouch = false; if (Input.GetKeyDown(KeyCode.S)) { isCrouch = true; } bool isJump = false; if (Input.GetKeyDown(KeyCode.W)&&! isCrouch) { isJump = true; } if (Input.GetKey(KeyCode.D)) { …设置方向向右.. if (Input.GetKey(KeyCode.LeftShift)) { if(!isJump&&! isCrouch) ..移动..播放跑步动画.. else if(!isCrouch) ..移动..播放跳跃动画.. else ..移动..播放蹲走动画.. } else { if(!isJump&&! isCrouch) ..移动..播放跑步动画.. else if(!isCrouch) ..移动..播放跳跃动画.. else ..移动..播放蹲走动画.. } } else if (Input.GetKey(KeyCode.A)) { …设置方向向左.. if(!isJump&&! isCrouch) ..移动..播放跑步动画.. else if(!isCrouch) ..移动..播放跳跃动画.. else ..移动..播放蹲走动画.. } else { if(!isJump&&! isCrouch) ..移动..播放跑步动画.. else if(!isCrouch) ..移动..播放跳跃动画.. else ..移动..播放蹲走动画.. } }
一个最简单的有限状态机阿 兰图灵提出的图灵机就是一种状态机,就是指一个抽象的机器,它有一条无限长的纸带TAPE,纸带分成了一个一个的小方格,每个方格有不同的颜色。有一个读 写头HEAD在纸带上移来移去。机器头有 一组内部状态,还有一些固定的程序。在每个时刻,机器头都要从当前纸带上读入一个方格信息,然后结合自己的内部状态查找程序表,根据程序输出信息到纸带方 格上,并转换自己的内部状态,然后进行移动。 准备工作
状态机需要满足的条件: enum&switch
public enum CharacterState { Idling = 0, Walking = 1, Jumping = 2, acting= 3, defending= 4, } public CharacterState heroState = CharacterState. Idling;
void handleInput() { switch(heroState) { case CharacterState. Idling: …播放空闲动画.. if…Input.GetKey –A,D. this. heroState = CharacterState. Walking; else if…Input.GetKey –w. this. heroState = CharacterState. Jumping; else if…Input.GetKey –J. this. heroState = CharacterState. acting; else if…Input.GetKey –I. this. heroState = CharacterState. defending; break; case CharacterState. Walking: if…Input.GetKey –A,D. …CharacterController移动操作.. else…Input.GetKeyUp – A,D… this. heroState = CharacterState. Idling; break; case CharacterState. Jumping: if(Input.GetKeyUp(KeyCode.W)) …CharacterController移动操作.. if(CharacterController.isGrounded) { this. heroState = CharacterState. Idling; } break; case CharacterState. acting: …播放攻击动画. chargeTime += Time.timeScale / Time.deltaTime; if(chargeTime>maxTime) { this. heroState = CharacterState. Idling; chargeTime = 0; } break; case CharacterState. defending: …播放防御动画. if(Input.GetKeyUp(KeyCode.I)) this. heroState = CharacterState. Idling; break; } }
c#的委托与事件
说起委托与事件,就肯定与观察者模式挂钩了。 using UnityEngine; using System.Collections; using System; public class InputEventArgs : EventArgs { public string input; public string addition1; public string addition2; public InputEventArgs(string _input, string _addition1, string _addition2) { this.input = _input; this.addition1 = _addition1; this.addition2 = _addition2; } }
public delegate void InputEventHandler(object sender, InputEventArgs e); public event InputEventHandler InputTran; InputEventArgs inputArgs = new InputEventArgs("","",""); State heroStateActVer; void Start() { personCtrl = this.GetComponent<HeroCtrl>(); heroStateActVer = new IdleStateActVer(this.gameObject); InputTran += new InputEventHandler(heroStateActVer.handleInput); } void Input_events(InputEventArgs e) { if (e != null) { InputTran(this, e); } } void Update() { if (Input.anyKeyDown) { foreach (char c in Input.inputString) { if (c != null) { inputArgs.input = c.ToString(); Input_events(inputArgs); } } } heroStateActVer.UpDate(); }
public void handleInput(object sender, InputEventArgs e) { input = e.input; switch (input) { case "j"://攻击 …转为攻击状态.. break; case "i"://防御 …转为防御状态… break; } }
状态模式
四人帮说: using UnityEngine; using System.Collections; public class State { protected static string input; protected GameObject Person; protected Hero Person_ctrl; protected float chargeTime; protected float MaxTime; public State(GameObject _Person) { this.Person = _Person; this.Person_ctrl = _Person.GetComponent<Hero>(); } public virtual void handleInput(object sender, InputEventArgs e) { } public virtual void UpDate() { } public virtual void UpDate() { } public virtual void Start() { } }
using UnityEngine; using System.Collections; public class ActState : State { public ActState(GameObject _Person) : base(_Person) { } public override void Start() { this.chargeTime = 0.0f; this.MaxTime =..攻击动画时间.. ..播放攻击动画.. } public override void handleInput(object sender, InputEventArgs e) { input = e.input; switch (input) { case "j"://连击 if (chargeTime > MaxTime - 0.1f) { Person_ctrl.GetActState(1).Start(); } break; case "i": //转换为防御状态 if (chargeTime > MaxTime - 0.1f) { Person_ctrl.SetActState(2); Person_ctrl.GetNowActState().Start(); } break; } } public override void UpDate() { if (chargeTime < MaxTime) chargeTime += Time.timeScale / Time.deltaTime; else { this.chargeTime = 0.0f; Person_ctrl.SetActState(0); Person_ctrl.GetNowActState().Start(); } } }
using UnityEngine; using System.Collections; public class AllState { public static State actState = new ActState(); public static State jumpState = new JumpState(); ……. }
private State[] hero_act_state = new State[3]; hero_act_state[0] = new IdleStateActVer(this.gameObject); hero_act_state[1] = new ActState(this.gameObject); hero_act_state[2] = new DefenseState(this.gameObject);
总结
在
有限状态机中,一般都是观察者模式与状态模式连用,状态模式把每个状态封装成类,来对每个输入消息(按键)处理,完全摆脱了大量if
else的纠缠,减轻了大量逻辑错误出现的可能,但是本身也有很多缺点,因为状态毕竟是有限的,,当状态少的时候可以运用自如,当状态多的时候10个以上
就已经结构非常复杂,而且容易出错,之前在游戏人工智能开发之6种决策方法提到如果用在AI上会产生一些问题,所以之后会发文讲状态机的进阶-分层有限状态机。 部分代码已共享至github 命令模式:游戏开发设计模式之命令模式(unity3d 示例实现) 对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现)
原型模式:游戏开发设计模式之原型模式 & unity3d JSON的使用(unity3d 示例实现) 博主近期渲染:最近用unity5弄的一些渲染
---- by wolf96 http://blog.csdn.net/wolf96 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论