赞
踩
更优雅的阅读 :
安全提示 - Sina.lt短网址
欢迎你在Notion里和我们互动,如有疑问也可评论提出。
游戏编程的开发中比较复杂的是状态处理(State Management)。参考以下片段:
- private void HandleInput() {
- if(Input.GetKeyDown(KeyCode.B){
- vY = JUMP_VELOCITY;
- setGraphics(IMAGE_JUMP);
- }
- }
按照代码所示,如果玩家按下B键,就会跳起,但这里存在一个(bug),如果玩家是不断的按下B键或是长按B键,那么游戏角色就会不断地往上飞。
这时候我们可以在代码中添加加一个旗标(Flag),如下:
- // isJumping 是记录玩家是否跳起的旗标
- bool isJumping = false;
-
- private void HandleInput() {
- if(Input.GetKeyDown(KeyCode.B) && !isJumping){
- // 跳起来。。。
- isJumping = true;
- }
- }
- // 省略重置 isJumping = false
但是这个解决方案很快就会在之后需要增加的功能上遇到瓶颈,比如如果要做双跳(Double Jump)怎么办?还是要蹲下怎么办?这个时候我们就会选用状态模式 (State Pattern)。
这种设计也称状态机(State Machine),需要具备以下几种自定规则:
接下来,我想着重介绍如何在Unity内,不用任何外部代码,架构起一个可视化的状态机。
在Unity技术的工作面试时,难免会慌手慌脚,所以如果用这个把游戏内部状态和视觉状态连接在一起,让你轻松有条理的地解释你的思维模式,让面试官大跌眼镜。(比如制作《糖果传奇》的King公司的其中一个技术面试题目就是当场制作宝石方块游戏,如果用状态机基本都会加分。)
我们将会自定义Unity动画系统里的状态机,同时额外添加一些功能,让我们能够更好的利用它。
首先编写一个继承 StateMachineBehaviour
的对象,这样我们就可以创建自定义状态,为状态机提供更简洁的界面,并启用可视化调试。这个新的对象我们可称为 LogicalStateMachineBehaviour
,然后参考以下编码。
- protected abstract void OnLogicalStateEnter(GameObject gameObject);
-
- protected abstract void OnLogicalStateUpdate(GameObject gameObject);
-
- protected abstract void OnLogicalStateExit(GameObject gameObject);
-
- protected abstract void ResetState(GameObject gameObject);
-
- public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
- {
- ResetState(ActiveAnimator.gameObject);
- OnLogicalStateEnter(ActiveAnimator.gameObject);
- }
-
- public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
- {
- OnLogicalStateUpdate(ActiveAnimator.gameObject);
- }
-
- public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
- {
- OnLogicalStateExit(ActiveAnimator.gameObject);
- }
为了方便调试,我们可以用我们已经做好的Trigger来做一个叫 Continue
的方法,可以迫使状态机进入下一个状态。
- protected Animator ActiveAnimator;
-
- protected void Continue()
- {
- if (!ActiveAnimator) return;
- ActiveAnimator.SetTrigger(Animator.StringToHash(Next));
- }
-
- public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
- {
- ActiveAnimator = animator;
- ResetState(ActiveAnimator.gameObject);
- ActiveAnimator.ResetTrigger(Animator.StringToHash(Next));
-
- OnLogicalStateEnter(ActiveAnimator.gameObject);
- }
通过在编辑器中为其创建 一个Inspector 按钮,可以更进一步地改良状态机。就我个人而言,我会直接使用Odin Inspector创建一个,但如果希望使用本机解决方案,也可以在这里找到。
瞧! 在项目中可使用的简单可视状态机,也可以在这里找到代码。
没有意外的话,每礼拜更新。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。