Unity 有限状态机(Finite State Machine)的理解 与 实现简单的可插拔(Pluggable)AI脚本对象。
2017-06-10 22:20
921 查看
#Unity 有限状态机(Finite State Machine)的理解 与 实现简单的可插拔AI脚本对象。
参考官方教程:Pluggable AI With Scriptable Objects
Github完整项目:TanksPluggableAI
大神Blog:【游戏设计模式】之三 状态模式、有限状态机 & Unity版本实现
一般的游戏AI都是使用状态机的设计模式来实现的。发现官方有教程,就跟了一遍,这里就总结一下。
先简单说一下状态模式。就是根据当前状态和对应条件,选则需要转换的下一个状态。例如本文的例子,坦克默认状态是巡逻(状态),在发现有敌人时(条件),转换成追杀(状态),在敌人逃脱或死掉了之后(条件),又变成巡逻(状态)。
游戏场景:绿色标签为巡逻点。蓝色标签为玩家出生点。红色为AI出生点。(如图玩家被两个AI追杀。)
Unity中文件分类层级如下。其中DefaultEnemyStats是默认AI的一些配置。包括攻击距离,移动速度,旋转速度等等。
通过上表其实可以发现有两个非常相似的动作,只是为了演示Alert Scanner 的。其实是可以优化的,就是修改Transition的结构,不再是只有两种状态选择,而是多种,这样就可以更好的重用状态。
参考官方教程:Pluggable AI With Scriptable Objects
Github完整项目:TanksPluggableAI
大神Blog:【游戏设计模式】之三 状态模式、有限状态机 & Unity版本实现
一般的游戏AI都是使用状态机的设计模式来实现的。发现官方有教程,就跟了一遍,这里就总结一下。
先简单说一下状态模式。就是根据当前状态和对应条件,选则需要转换的下一个状态。例如本文的例子,坦克默认状态是巡逻(状态),在发现有敌人时(条件),转换成追杀(状态),在敌人逃脱或死掉了之后(条件),又变成巡逻(状态)。
游戏场景:绿色标签为巡逻点。蓝色标签为玩家出生点。红色为AI出生点。(如图玩家被两个AI追杀。)
AI对象结构
每个AI对象都有一个状态控制器(StateController)脚本组件,包含一个当前状态(State),且状态包含需要执行动作(Action),还有状态转换的条件(Transition)。Unity中文件分类层级如下。其中DefaultEnemyStats是默认AI的一些配置。包括攻击距离,移动速度,旋转速度等等。
State (状态)
using UnityEngine; [CreateAssetMenu (menuName = "PluggableAI/State")] public class State : ScriptableObject { public Action[] actions; //动作 public Transition[] transitions; //通过决定,选择下一种动作决定 public Color sceneGizmoColor = Color.gray; //拿来渲染eyes的Gizmos颜色 //每一帧更新状态,在StateController的OnUpdate中调用。 public void UpdateState(StateController controller) { DoActions(controller); //执行动作 CheckTransition(controller); //检测转换状态 } //顺序执行动作列表的动作。 private void DoActions(StateController controller) { for (int i = 0; i < actions.Length; i++) actions[i].Act(controller); } //检查所有转换状态,并改变状态。 private void CheckTransition(StateController controller) { for (int i = 0; i < transitions.Length; i++) { //这里条件转换只有两个,所以直接用Bool类型来判断。当然也可以有多种条件转换。 bool decisionSucceeded = transitions[i].decision.Decide(controller); if (decisionSucceeded) controller.TransitionToState(transitions[i].trueState); else controller.TransitionToState(transitions[i].falseState); } } }
状态名 | 说明 | 配置 |
---|---|---|
Remain State | 保持原来状态。不包含任何属性。 | 略。 |
PatrolChaser | 巡逻者状态。在巡逻点之间巡逻,如果检测到敌人,转为追杀状态。 | |
ChaseChaser | 追杀者状态。导航到目标一定距离并持续攻击,直到目标死掉,转回巡逻者模式。 | |
PatrolScanner | 同Patrol Chaser。巡逻到敌人,转为追杀。 | |
ChaseChaser | 同Chase Chaser 。追杀敌人,但到目标死掉,转换成警觉模式。 | |
AlertScanner | 警觉模式。其实就是旋转扫描敌人,直到扫描到目标或超过了一定时间。 |
Action(动作)
using UnityEngine; public abstract class Action : ScriptableObject { //State直接调用这个方法来执行动作。 public abstract void Act(StateController controller); }
动作名 | 说明 | 原理 |
---|---|---|
PatrolAction | 巡逻动作。从StateController搞来巡逻点列表。在这些巡逻点之间巡逻移动。 | 设置巡逻点为导航目标点,到达后设置下一个巡逻点为导航点。 |
ChaseAction | 追随动作。最短距离到达目标。 | 设置目标为导航目标点,导航过去就是了。 |
AttackAction | 攻击动作。攻击目标。 | 射出检测射线(红色的),检测到目标就发炮攻击。 |
Decision(决定)
using UnityEngine; public abstract class Decision : ScriptableObject { //通过这个方法的返回值来判断决定的选择。 public abstract bool Decide(StateController controller); }
决定名 | 说明 | 原理 |
---|---|---|
LookDecision | 检测决定。检测到目标就设置为追踪目标,并且返回True。 | 射出检测球体射线(绿色的)来检测。 |
ActiveStateDecision | 活动状态决定。就是判断追踪的目标是否active(激活状态)。 | 直接返回追踪目标的active的bool值。 |
ScanDecision | 扫描决定。说是扫描其实并没有扫描,只是在转圈而已。一直转到外部条件改变状态,或者超过了扫描限定的时间。 | 停止导航。配合Time.deltaTime旋转自己。返回是否超过扫描限定时间。 |
Transitions(状态转换)
//状态转换。通过决定的返回值,选则两种状态中其中一个 [System.Serializable] public class Transition { public Decision decision; public State trueState; public State falseState; }
测试结果
第一种,巡逻->发现目标->追杀->目标死亡->巡逻。(颜色配合下图样例使用。)
1. 起始 Patrol Chase 状态,巡逻点之间移动,还没有检测到目标,眼里射出的是清澈的绿色。
2. 发现了目标,转为Chase Chaser 状态,射出了充满愤怒的红色射线,并且一直攻击目标。
3. 当目标化为灰烬,转回 Patrol Chase 状态。
第二种,巡逻->发现目标->追杀->目标死亡->旋转扫描目标->{两种情况:1. 发现目标,回到第二步。2. 超过扫描时间,回到第一步(巡逻)。(颜色配合下图样例使用。)
1. 起始 Patrol Scanner 状态,巡逻,眼里射出的是原谅的绿色。
2. 发现刚刚杀了蓝孩子的小红,转为 Chase Scanner 状态,追杀之。
3. 杀掉小红之后,转为 Alert Scanner 状态。旋转扫描周围是否有敌人。
4. 没有扫到,回到 Patrol Scanner 状态。
相关文章推荐
- 【Unity】Finite State Machine 有限状态机
- 有限状态机(Finite State Machine)在游戏中的应用和实现
- 迭代器就是重复地做一些事情,可以简单的理解为循环,在python中实现了__iter__方法的对象是可迭代的,实现了next()方法的对象是迭代器,这样说起来有
- Unity简单的实现动画三连击脚本
- Finite State Machine 有限状态机
- [Unity Tips]在脚本中使用MonoBehavior.OnAnimatorMove()和StateMachineBehavior.OnStateMove()改变根运动
- 有限状态机——The finite state machine
- Unity-Animator深入系列---StateMachineBehaviour状态机脚本学习
- 有限状态机实现简单的AI状态(巡逻,追逐玩家,攻击)
- unity 按钮 两态处理,简单脚本实现
- 分享一个简单的unityAI框架,基于神经网络和遗传算法,可以简单的实现自成长的游戏对象
- 简单理解javascript中的原型对象,实现对之间共享属性和行为
- unity5, animator state machine, 无条件transition实现播放动画序列
- 简单理解javascript中的原型对象,实现对之间共享属性和行为
- [转]浅析C++中虚函数的调用及对象的内部布局(利用汇编深刻理解C++虚函数底层实现机制)
- 在.net执行sql脚本的简单实现
- 利用.net(C#)执行sql脚本的简单实现
- 简单的脚本实现电量警告[zt]
- [python]有限状态机(FSM)简单实现
- 超简单的邮件快速登录脚本制作实现方法[转]