最近在学习使用行为树做AI,决定把学到的贡献出来,抛砖引玉,希望可以认识到更多大牛 -- 首先我们了解下什么是行为树和为什么要使用行为树。 在我们项目中如果需要做一个AI敌人,比如做一个手游 某民突击里面的普通步兵,那么这个步兵的基本ai 就是 从出生点出来后获取一个躲避点,然后向躲避点跑动,当到达躲避点后,开始做各种动作 向玩家开枪,当开枪完后执行躲避动作,躲避动作完成后可能继续开枪,或者又跑到其他躲避点,然后就是一个循环。 那么做这个ai 一般会用fsm状态机来写,通过不同的状态 来调用具体的方法,状态机有效的解决了代码的扩展性问题,使得开发变得很清晰,代码之间的耦合性也分的比较好。 但是,状态机也有些弊端,比如代码不能重用,如果一个项目特别的大,状态之间的切换会变得很复杂,维护状态机也会变得麻烦。所以这个时候就需要用行为树来做解决方案了。当然,这里指的是状态机做得足够大才会出现的问题,目前我做的ai还不至于到状态机撑爆,那你说我为什么我还要学行为树呢 ,<ignore_js_op> ![]() 好,废话说了那么多,那我们现在来进入正题。 ------- 首先我们用的是Behave 行为树插件,目前这个插件好像unity商店已经没有了,我会在后面提供给大家。 首先导入这个插件, 会在项目中出现一个 <ignore_js_op> ![]() 然后我们点击project的create library <ignore_js_op> ![]() 然后unity会多出来两个窗口 一个behave editor 和 behave browse 我们的行为树就是在这两个面板进行创建和编辑了 然后我们点击behave browse 面板的create create一个collection ,继续 再create一个tree 这样我们就有一个空的行为树了 ,接下来 我们选中新创建的NewTree1 在behave editor面板就会多出来7个选项在下面, 这7个就是我们要学的行为树的内容了 后面我会逐个介绍 , 首先介绍 那个小圆圈的那个 就是一个行为节点 ,我们把小圆圈拖到上面,然后改名叫MyAction, 然后在顶部中间的方块拉出一条线,连线到我们的小圆圈顶上,这样就建立起来了一个连接。<ignore_js_op> ![]() ok,现在我们画出来了一个行为节点,怎么去执行这个节点呢,或者说去编辑这个节点的代码呢 ,这时候我们新建一个脚本,就叫MyAction.cs 然后添加引用 using Behave.Runtime; using Tree = Behave.Runtime.Tree; 声明一个静态变量,再引用行为树。 在MonoBehaviour后面再加一个继承,IAgent 接口,然后实现这些方法 。 增加一个类Tree m_Tree; 再改写Start方法为 IEnumerator Start() Start方法使用库里面的InstantiateTree 静态方法,再用一个死循环来调用一个AIUpdate方法 在AIUpdate里面执行 行为树的Tick() 方法,每当行为节点被调用时,都会调用这个Tick方法就是实例的默认方法,我们开始重新改写这几个方法,换成我们自己的方法。 好,现在我们开始改写从接口实现下来的方法,一共有3个 public void Reset(Tree sender){ } public int SelectTopPriority(Tree sender, params int[] IDs){ return 0; } public BehaveResult Tick(Tree sender, bool init) { Debug.Log("调用系统的Tick方法 " + (BLAgentBehaveLib.IsAction(sender.ActiveID) ? "Action " : "Decorator ") + " ... " + (BLAgentBehaveLib.IsAction(sender.ActiveID) ? ((BLAgentBehaveLib.ActionType)sender.ActiveID).ToString() : ((BLAgentBehaveLib.DecoratorType)sender.ActiveID).ToString()) ); return BehaveResult.Success; } 这里的tick 就会输入我们自己的tick方法了 好了,这个时候就到我们刚才的MyAction的行为节点的代码了 现在 ,我们开始加入实现MyAction 节点的代码 这里有个命名规则 BehaveResult Tick+"你的行为节点的名字"+Action(Tree sender) [C#] 纯文本查看 复制代码
记住,脚本的方法名字一定要和行为节点一模一样 否则他就调不到,就回去调Tick方法了 这时候你的代码应该是这样的 <ignore_js_op> ![]() 然后我们运行一下,就可以看到我们写的myAction方法了 <ignore_js_op> ![]() 好了,我们第一天的介绍就到这里,目前我们就学习了 behave 这个插件的基本搭建和调用了一个最简单的Action节点了 下面是源码 里面还有我新的学习情况,会多出几个内容,将在后面在介绍 写得好辛苦,就小小收几个币吧 unity3d 行为树;unity 本身的行为树插件; |