基于行为树的AI框架

所谓AI即人工智能,例如扫荡副本,boss,小怪有智慧地攻击玩家等pve(player vs Environment)的地方都会用到。程序可以设计不同的AI来调整难度,让boss小怪显得更加有智慧。实现AI的方式有很多种,从有限状态机(FSM),分层有限状态机(HFSM)到决策树(Decision Tree),都可以维护庞大数量的知识条目。本文要介绍的是Next-Gen AI的行为树(Behavior Tree)。

行为树(Behavior Tree) 具有如下的特性:
 它只有4大类型的Node:
  * Composite Node  组合节点
  * Decorator Node  装饰节点
  * Condition Node  条件节点
  * Action Node   行为节点
  任何Node被执行后,必须向其Parent Node报告执行结果:成功 / 失败。
  这简单的成功 / 失败汇报原则被很巧妙地用于控制整棵树的决策方向。

其中,组合节点有顺序节点(SequenceNode有一个子节点返回false就结束,相当于与运算)和选择节点(SelectorNode有一个子节点返回true就结束,相当于或运算)两种,条件节点和行为节点属于叶子节点,即没有子节点。光说文字很难理解。一个比较有名的AI行为树如下

基于行为树的AI框架_第1张图片


下面是一个项目中用到的AI行为树框架

类继承关系如下基于行为树的AI框架_第2张图片

根据上面各节点的描述,有以下流程图。

基于行为树的AI框架_第3张图片

具体的伪代码如下

using System;

public enum State
{
    INIT,  //初始化
    PENDING,  //正在执行
    FINISH,  //成功
    FAIL  //失败
}

//基类BTNode
public class BTNode
{
    State state;
    ComponentNode parent;
    public virtual void reset()
    {
      state = State.Init;
    }
   //执行方法,用于重载override    
   public virtual void execute(AIControl agent)
   {
       
   }

   public virtual void finish(AIControl agent, State stat)
   {
       this.state = stat;
       if(this.parent!=null)
       {
           //把state传给父节点
           this.parent.tryMoveNext(agent, stat);
       }
   }
}

//复合节点
public class ComponentNode:BTNode
{
    List childs; //子节点
    bool isFirstExe; //是否第一次执行,用于初始化
    addChild(){};//添加子节点
    removeChild(){};//移除子节点
    override finish(){base.finish();}
    moveNext()
    {
        if(CanMoveNext())
        {
            nextChild.execute();
        }
        else
        {
            moveEnd();
        }
    }
    //先判断条件是否能执行下一个子节点再执行
    tryMoveNext(State stat)
    {
         if(checkState(stat))
         {
             moveNext();
         }
    }

    override execute()
    {
       if(isFistExe){isFirstExe = false;beforeFirstExecute();}
       moveNext();
    }

    virtual beforeFirstExecute(){}//用于初始化
    virtual checkState(){}//用于override
    virtual moveEnd(){}   //用于override
}

public class SequenceNode : ComponentNode
{
    override bool checkState(State stat)
    {
         if(stat == State.Fail)
         {
             finish(State.fail);
             return false; 
         }
         return true;
    }

    override void moveEnd()
    {
        finish(State.finish);
    }
}

public class SelectorNode : ComponentNode
{
    override bool checkState(State stat)
    {
         if(stat == State.finish)
         {
             finish(State.finish);
             return false;
          }
          return true; 
   }


    override void moveEnd()
    {
        finish(State.Fail);
    }
}

public class BehaviorNode:BTNode
{
    
}
//条件节点
class ConditionNode : BehaviorNode
{
    override void execute()
    {
        if(condition())
        {
            finish(State.finish);
        }
        else
        {
            finish(State.fail);
        }
    }
    virtual bool condition(){}
}

//行为节点
class ActionNode:BehaviorNode
{
   virtual void execute()
   {
       finish(State.pending);
   }
}
//具体实现的选择节点
class xxx:SelectorNode
{
    override void beforeFirstExecute(){}
    override void execute(){}
}
//具体实现的顺序节点
class yyy:SequenceNode
{
    override void beforeFirstExecute(){}
    override void execute(){}
}
//具体实现的条件节点
class yyy : ConditionNode
{
     override bool condition(){}
}
//具体实现的行为节点
class zzz:ActionNode
{
    override void execute(){}
}
//AIControl存放一颗AI行为树的根节点,每隔一段时间从根节点遍历行为树,根据当前的情况实现不同的分支叶子节点,从而实现具体的游戏逻辑
class AIControl
{
    root = 读表根节点
    think()
    {
       每隔一段时间 root.execute(this);   
    }    
}

以上是一个底层的行为树基本框架,具体的程序实现,需要根据策划的需求,实现各个具体的节点,一般是继承选择节点,顺序节点,条件节点,行为节点用得比较多。一些需要循环执行等特殊操作的装饰类节点在项目中比较少用,在这里也就没有具体实现了。项目中通过读取策划导出的约定好的AI行为树文件,在逻辑层调用AIControl.think实现游戏对象有智慧地思考行动。

你可能感兴趣的:(unity3d)