开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

蛮牛译馆

关注:531

当前位置:游戏蛮牛 技术专区 蛮牛译馆

查看: 1329|回复: 9

[外文翻译] 有限状态机在人工智能中的运用

[复制链接]  [移动端链接]
7日久生情
1950/5000
排名
1138
昨日变化
1

52

主题

205

帖子

1950

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
69113
好友
11
蛮牛币
871
威望
0
注册时间
2015-1-17
在线时间
651 小时
最后登录
2017-5-12

蛮牛译员

发表于 2016-7-28 13:53:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x





目录

1.Set up thescene 场景布局

2.Create andplace Game Objects 创建和放置游戏物体

3.Implement theBoxMovement Script 角色控制脚本的实现

4.FSM ModelledScript  状态机脚本

5.AI Script forthe Box   角色的AI脚本


目标

Main objective of this post is to give youan idea about how to work with FINITE State Machine Model in AI Implementationin Unity.

本教程目的在于帮助您实现有限状态机与人工智能的集成开发。


Basics of FSM:有限状态机简介:

Finite State Machine Framework isperfect for implementing AI in games, producing great results without a complexcode. It is a model of computation based on a hypothetical machine made of oneor more states. Only a single state can be active at a time, so the machinemust transition from one state to another in order to perform differentactions.

我们发现在许多大型项目的AI框架中都有有限状态机的影子,究其原因在于状态机可大幅度减少代码的编写。概括起来,状态机的计算模型无非是基于模拟机器的一个或多个状态的相互切换。由于在某个时间点只能激活一种状态,所以为了使角色动作协调且真实,这时需要进行状态迁移。

Finite State Machine Frameworks arecommonly used to manage, organize and represent an execution flow of differentstates, which is very useful in implementing AI in games. The "brain"of an enemy, for instance, can be implemented using a FSM: every staterepresents an action, such as Patrol, Chase, Evade or Shoot or any other kindof actions.

因为有限状态机能有效地管理,组织和呈现各种状态流,所以被大规模应用于游戏领域的AI仿真。打个比方,我们可以对一个敌人应用状态机去实现巡逻,追逐,闪避以及射击等各种行为。

AI FSMs work same as Unity's FSMs, where one animation state changes to another as per therequirement. AI FSM can be implemented either by using third party plug-inslike Behave or it can be implemented directly by scripting as well.

AI状态机的工作原理类似于Unity的动画状态机,即模拟人物角色的动画状态迁移。它一般通过第三方插件(如Behave)或者代码编写来实现。

To get a basic Idea of Finite StateMachine Framework, we will implement one tutorial in the simplest way,using the switch statements. Then we’ll study how to use a framework to makethe AI implementations easier to manage and extend.

为了加深对有限状态机框架的理解,首先我们会通过switch语句来学习如何实现一个简版状态机,接着我们使用一个状态机框架去实现和拓展更易于控制的AI技术点。


Follow the below steps to implement simpleFSM.请参照下述步骤完成一个简版的状态机。

Here we will have two Boxes, where one boxwill be controlled by the player and the other will be AI controlled. This AIcontrolled box will be either in chasing state or in patrolling state, i.e. thebox will start chasing player box, once the player box comes in the proximityof the AI controlled box. And it will switch back to patrol state if the playerevades far enough from AI's defined vision.

首先我们创建2个游戏物体(盒子),一个角色将由我们控制,另外一个使用AI进行控制。AI控制的角色有2种状态---巡逻或者追逐,即当玩家角色进入AI角色的巡逻范围内时,AI角色此时状态为追逐,或则当玩家角色在AI角色的巡逻范围外时,AI角色跳转状态为巡逻。


Step 1 Set up the scene 1.场景布局

Take One Plane and Two Boxes and Set up thescene as shown in the following figure.

新建一个平面和2个游戏角色(用盒子进行替代),如下图所示。

2.png


Step 2 Create and place GameObjects 2.创建空的游戏物体并放置在Wanderer Points

Create empty game objects and place it asWanderer Points. Place these empty game objects around the plane as per yourchoice. Here the Blue Cube is the AI cube and the Red One is the Playercontrolled cube. Place them at a distance far enough, so that AI doesn't startfollowing at the start itself.

创建空的游戏物体并将其置于Wanderer Points【路径点集合】下,然后在该平面上随意放置

游戏物体。我们把蓝色Cube设置为AI角色而红色则为玩家角色。需要注意的是,尽可能地放置远一点,不然AI角色一开始就会追逐玩家角色。


Step 3 Implement the BoxMovementScript玩家角色控制脚本的实现

Implement the BoxMovement Scriptto the player controlled box as given below.

玩家角色控制脚本的实现如下所示。


[C#] 纯文本查看 复制代码
public class BoxMovementScript : MonoBehaviour



{



        public float speed = 0.1f; //玩家移动速度



        private Vector3 positionVector3; //玩家位置



        void Update ()



        {        



                InitializePosition (); //初始化玩家位置



                if (Input.GetKey (KeyCode.LeftArrow)) { //左



                        GoLeft ();



                }



                if (Input.GetKey (KeyCode.RightArrow)) {//右



                        GoRight ();



                }



                if (Input.GetKey (KeyCode.UpArrow)) { //上



                        GoTop ();



                }



                if (Input.GetKey (KeyCode.DownArrow)) {//下



                        GoDown ();



                }



                RotateNow ();//旋转



        }



        private void InitializePosition ()//初始化玩家位置



        {



                positionVector3 = transform.position;//获取玩家位置



        }



        private void RotateNow () //旋转



        {



                Quaternion targetRotation = Quaternion.LookRotation (transform.position - positionVector3);



                transform.rotation = targetRotation;



        }



        private void GoLeft ()



        {



                transform.position = transform.position + new Vector3 (-speed, 0, 0);            



        }



        private void GoRight ()



        {



                transform.position = transform.position + new Vector3 (speed, 0, 0);



        }



        private void GoTop ()



        {



                transform.position = transform.position + new Vector3 (0, 0, speed);



        }



        private void GoDown ()



        {



                transform.position = transform.position + new Vector3 (0, 0, -speed);



        }



}


Step 4 FSM Modelled Script 4. 状态机脚本

Construct an FSM Modelled Script as givenbelow. 将下列代码复制进新建的FSM脚本

[C#] 纯文本查看 复制代码
public class FSM : MonoBehaviour



{



        //Player Transform



        protected Transform playerTransform; //玩家位置



        //Next destination position of the Box



        protected Vector3 destPos; //目标点



        //List of points for patrolling



        protected GameObject[] pointList; //路径点数组



        protected virtual void Initialize (){ //定义初始化虚函数



        }



        protected virtual void FSMUpdate (){//定义状态机更新虚函数



        }



        protected virtual void FSMFixedUpdate (){////定义状态机固定虚函数



        }



        void Start ()



        {



                Initialize ();



        }



        void Update ()



        {



                FSMUpdate ();



        }



        void FixedUpdate ()



        {



                FSMFixedUpdate ();



        }



}



Step 5 AI Script for the Box  AI角色的控制脚本

Construct an AI Script for the Box thatextends the Above FSM Modelled script.

新建一个继承自FSMAI脚本

[C#] 纯文本查看 复制代码
public class BoxFSM : FSM //继承自FSM



{



        public enum FSMState //状态机的各状态



        {



                None, //待机



                Patrol,//巡逻



                Chase,//追逐



        }



        //Current state that the Box is in



        public FSMState curState; //当前状态机



        //Speed of the Box



        private float curSpeed; //当前速度



        //Box Rotation Speed



        private float curRotSpeed;//选择速度



 



        //Initialize the Finite state machine for the  AI Driven Box



        protected override void Initialize () //重写初始化函数



        {



                curState = FSMState.Patrol;



                curSpeed = 5.0f;



                curRotSpeed = 1.5f;                



                



                //Get the list of points



                pointList = GameObject.FindGameObjectsWithTag ("WandarPoint");



                



                //Set Random destination point for the patrol state first



                FindNextPoint ();



                



                //Get the target enemy(Player)



                GameObject objPlayer = GameObject.FindGameObjectWithTag ("Player");



                playerTransform = objPlayer.transform;



                



                if (!playerTransform)



                        print ("Player doesn't exist.. Please add one " + "with Tag named 'Player'");



                



        }



 



        //Update each frame



        protected override void FSMUpdate () //重写状态机更新函数



        {



                switch (curState) {



                case FSMState.Patrol:



                        UpdatePatrolState ();



                        break;



                case FSMState.Chase:



                        UpdateChaseState ();



                        break;



                }



        }



 



        protected void UpdatePatrolState () //巡逻状态更新



        {



                //Find
 another random patrol point on reaching the current Point 


                //point is reached



                if (Vector3.Distance (transform.position, destPos) <= 2.5f) {



                        print ("Reached to the destination point\n" + "calculating the next point");



                        FindNextPoint ();



                }



 



                //Check the distance with player Box



                //When the distance is near, transition to chase state



                else if (Vector3.Distance (transform.position, playerTransform.position) <= 15.0f) {



                        print ("Switch to Chase State");



                        curState = FSMState.Chase;



                }



                



                //Rotate to the target point



                Quaternion targetRotation = Quaternion.LookRotation (destPos - transform.position);



                transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, Time.deltaTime * curRotSpeed);



                



                //Go Forward



                transform.Translate (Vector3.forward * Time.deltaTime * curSpeed);



        }



 



        protected void FindNextPoint () //下一个目标点位置



        {



                print ("Finding next point");



                int rndIndex = Random.Range (0, pointList.Length);



                float rndRadius = 5.0f;



                Vector3 rndPosition = Vector3.zero;



                destPos = pointList [rndIndex].transform.position + rndPosition;



                



                //Check Range to Move and decide the random point



                //as the same as before



                if (IsInCurrentRange (destPos)) {



                        rndPosition = new Vector3 (Random.Range (-rndRadius, rndRadius), 0.0f, Random.Range (-rndRadius, rndRadius));



                        destPos = pointList [rndIndex].transform.position + rndPosition;



                }



        }



 



        protected bool IsInCurrentRange (Vector3 pos) //是否在范围内



        {



                float xPos = Mathf.Abs (pos.x - transform.position.x);



                float zPos = Mathf.Abs (pos.z - transform.position.z);



                if (xPos <= 8 && zPos <= 8)



                        return true;



                return false;



        }



 



        protected void UpdateChaseState () //追逐状态更新


       {


               //Set the target position as the player position


               destPos = playerTransform.position;



                //Check the distance with player Box When



                float dist = Vector3.Distance (transform.position, playerTransform.position);



                



                //Go back to patrol as player is now too far



                if (dist >= 15.0f) {



                        curState = FSMState.Patrol;



                        FindNextPoint ();



                }



                //Rotate to the target point



                Quaternion targetRotation = Quaternion.LookRotation (destPos - transform.position);



                transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, Time.deltaTime * curRotSpeed);



                //Go Forward



                transform.Translate (Vector3.forward * Time.deltaTime * curSpeed);



        }



}


Apply this script to the cube which isgoing to follow the player, also do not forget to tag the playeras Player and wander points as WandarPoint , now as seen inthe script the FSMUpdate() method will be called which is overriddenin the child class and hence it will be executed on each Update().

把上述脚本应用AI角色(蓝色cube),即追逐玩家角色的那个角色。当然,别忘记1.设置player标签为Player2.将路径点置于WandarPoint 其下,接着会调用子类的FSMUpdate()对各种状态进行更新。


Here the switch case is implemented whichwill be used to execute actions as per the current state. Thus extension of AIis quite simple by just adding new states. Initialize() method isalso overridden and will be called on Start() methodexecution. UpdatePatrolState() will be executed on each update whencurrent state is to patrol around wanderer points and same will happenfor UpdateChaseState() , when the player comes in proximity of the AIBox.

这个状态机框架可通过switch~case语句实现在每一帧对游戏物体的状态进行更新,并易于扩展和添加其他状态。Initialize() 会在子类中进行重写,然后在start方法中进行执行。 UpdatePatrolState()方法会在每一帧进行对巡逻状态进行更新,类似于的还有UpdateChaseState()方法。


State Change is checked at every Update, ifwhen patrolling, the player comes in the vision of the AI Box, the state willbe changed to patrolling and same kind of check is kept in chase mode to checkif player has moved out of its vision, then switch back to patrol state.

我们会在每一帧对状态迁移进行更新,如果当前状态为巡逻且玩家角色在AI角色视野内时,此时状态机会从巡逻跳转到追逐,在追逐过程中AI角色会不停计算与玩家角色的距离,如果玩家角色离开了巡逻范围,那么其状态会变为巡逻。


Conclusion: 结论:

FSM's are quite easy to understand andimplement, FSMs can be used for implementing complex AI decisions states withquite simplicity. They can also be represented using a graph, which allows adeveloper to understand easily and hence the developer can tweak, change andoptimize the final result.

通过上述案例可知,有限状态机非常容易理解和实现,所以常用于简化复杂的AI逻辑推断。当然您也可以使用图示法来呈现一个状态机,可视化的编辑界面会让开发者更容易对结果进行调整,修改和优化。

The implementation of a FSM using functionsor methods to represent states is simple, powerful and easily extensible. Evenmore complex AI can be applied using a stack-based FSM, which ensures amanageable and stable execution flow without affecting the code negatively. Somake your enemies smarter using Finite State Machines and make your games asuccess.

通过封装函数和方法来实现一个有限状态机的状态呈现,这种做法所构建的框架函数简单,功能强大,易于扩展。复杂的AI逻辑框架可以尝试选用基于栈的状态机,从而保证逻辑和功能的流操作正常执行。综上所述,如果你想让你的敌人更加智能和游戏更加多人青睐的话,尝试使用下有限状态机吧。


原文作者:Rudra Gesota

原文链接:

http://www.theappguruz.com/blog/ai-implementation-using-finite-state-machine-model


附工程目录

AI-Implementation-using-FINITE-State-Machine-Model-master.zip

120.87 KB, 下载次数: 35


回复

使用道具 举报

排名
25448
昨日变化
16

0

主题

26

帖子

52

积分

Rank: 2Rank: 2

UID
92432
好友
0
蛮牛币
87
威望
0
注册时间
2015-4-15
在线时间
19 小时
最后登录
2016-9-21
发表于 2016-7-28 17:35:57 | 显示全部楼层
支持赞一个

回复

使用道具 举报

6蛮牛粉丝
1122/1500
排名
2438
昨日变化
6

5

主题

397

帖子

1122

积分

Rank: 6Rank: 6Rank: 6

UID
68430
好友
0
蛮牛币
5084
威望
0
注册时间
2015-1-14
在线时间
290 小时
最后登录
2017-5-26
发表于 2016-7-30 15:16:44 | 显示全部楼层
点个赞,但是这种设计方式,个人觉得,当应用到游戏内的时候,策划的脑洞跟你代码的扩展工作量很大·~~

回复 支持 反对

使用道具 举报

9以坛为家
17005/50000
排名
1872
昨日变化
8

9

主题

1万

帖子

1万

积分

Rank: 9Rank: 9Rank: 9

UID
78862
好友
5
蛮牛币
2678
威望
0
注册时间
2015-3-11
在线时间
918 小时
最后登录
2017-5-26
QQ
发表于 2016-7-31 08:21:03 | 显示全部楼层
前排占座

回复

使用道具 举报

3偶尔光临
224/300
排名
10055
昨日变化
10

2

主题

78

帖子

224

积分

Rank: 3Rank: 3Rank: 3

UID
148779
好友
0
蛮牛币
243
威望
0
注册时间
2016-5-16
在线时间
80 小时
最后登录
2016-10-9
发表于 2016-8-3 14:39:47 | 显示全部楼层
代码看上去更具有可读性,赞

回复 支持 反对

使用道具 举报

7日久生情
2408/5000
排名
513
昨日变化

8

主题

114

帖子

2408

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
81237
好友
1
蛮牛币
2378
威望
0
注册时间
2015-3-18
在线时间
1174 小时
最后登录
2017-5-26
发表于 2016-8-3 15:10:58 | 显示全部楼层
这种实现方式,AI简单的还可以用,如果AI复杂的话,代码逻辑会乱的

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1245/1500
排名
4740
昨日变化
3

2

主题

776

帖子

1245

积分

Rank: 6Rank: 6Rank: 6

UID
92518
好友
1
蛮牛币
2466
威望
0
注册时间
2015-4-15
在线时间
277 小时
最后登录
2017-4-6
发表于 2016-11-14 14:50:40 | 显示全部楼层
这就是有限状态机?

回复 支持 反对

使用道具 举报

7日久生情
1950/5000
排名
1138
昨日变化
1

52

主题

205

帖子

1950

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
69113
好友
11
蛮牛币
871
威望
0
注册时间
2015-1-17
在线时间
651 小时
最后登录
2017-5-12

蛮牛译员

 楼主| 发表于 2016-11-14 19:57:22 | 显示全部楼层
825 发表于 2016-11-14 14:50
这就是有限状态机?

是的。可能由于脚本编辑的问题,存在某些阅读问题,建议您下载工程项目进行阅读,谢谢您的支持
[发帖际遇]: 汉家郎 在论坛发帖时没有注意,被小偷偷去了 1 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

2初来乍到
100/150
排名
11612
昨日变化
8

0

主题

25

帖子

100

积分

Rank: 2Rank: 2

UID
175567
好友
0
蛮牛币
163
威望
0
注册时间
2016-10-14
在线时间
29 小时
最后登录
2017-5-24
发表于 2017-1-7 15:32:41 | 显示全部楼层
赞一个 好人啊

回复

使用道具 举报

4四处流浪
476/500
排名
7065
昨日变化
73

1

主题

263

帖子

476

积分

Rank: 4

UID
206456
好友
0
蛮牛币
505
威望
0
注册时间
2017-2-14
在线时间
92 小时
最后登录
2017-5-25
发表于 2017-3-2 08:49:00 | 显示全部楼层
还可以接受

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表