跳到主要内容
P小二 P小二
← 返回文章 • 游戏AI • • 约 6 分钟

07.游戏AI方法之行为树

GameAI: 07.游戏AI方法之行为树

行为树(Behavior Tree) 是和分层状态机类似的知识系统,主要是用来描述在有限的任务集合中的各种转换。目前,行为树是创建AI角色的主导性工具。

行为树

行为树算是多种技术的一个综合,包括了分层状态机,调度,路径规划和动作执行等。 行为树和分层状态机相比,它模块化,易于理解,对于非开发人员也是非常友好,它们的主要区别是行为树主要是行为构成,而非状态。

行为树是一种树状结构,节点有三种类型: 序列节点,选择节点和装饰节点。

序列节点

序列节点

按顺序执行多个子节点,如果遇到一个子节点不能执行,那就不继续执行。

按顺序执行多个子节点,如果遇到一个子节点不能执行,那就不继续执行。

例子: 先判断敌人是否可见,可见才走开。

选择节点

选择节点

按顺序执行多个子节点,如果遇到一个子节点执行成功,那就不继续执行。

按顺序执行多个子节点,如果遇到一个子节点执行成功,那就不继续执行。

例子: 如果执行攻击成功,那不执行嘲讽和凝视。

装饰节点

装饰节点,类似于装饰器模式,是用来以某种方式修改其他节点行为的。比如:结果取反/并/或,重复执行,获取执行时间等辅助功能。

所以,行为树基础节点只有序列节点和选择节点。

复合节点

复合节点,顾名思义就是把上面的两个节点结合起来。

比如,下面就是两个序列节点和一个选择节点组合。

比如,下面就是两个序列节点和一个选择节点组合。

吃豆人的行为树

吃豆人的行为树

上面是吃豆人的一个简单行为树。

处于寻找豆子的吃豆人,会按照顺序进行移动,找到豆子和吃下豆子等行为。 直到发现鬼魂为止。

在移动的时候,吃豆人会选择一个没有鬼魂的通道进行移动。

行为树实现

创建一个Task的基类:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Task : MonoBehaviour {
    public List children;
    protected bool result = false;
    protected bool isDone = false;}
public virtual void SetResult(bool r) {
    result = r;
    isDone = true;}
public virtual IEnumerator Run(){
    SetResult(true);
    yield break;}
public virtual IEnumerator RuntTask(){
   yield result StartCorutine(Run());}

创建一个ConditionBT类:

using UnityEngine;
using System.Collections;
public class ConditionBT: Task{
    public override IEnumerator Run()
    {
        isDone = false;
        bool r = false;
        //todo
        //编写你的行为逻辑
        SetResult(r);
        yield break;
    }}

然后再来一个ActionBT类:

using UnityEngine;
using System.Collections;
public class ActionBT: Task{
    public override IEnumerator Run()
    {
        isDone = false;
               //todo
        //编写你的行为逻辑
        return base.Run();
    }}

最后分别实现Sequence和Selector类。

using UnityEngine;
using System.Collections;
public class Sequence: Task{
    public override void SetResult(bool r)
     {
        if (r == true)
            isDone = true;
            }
    public override IEnumerator RuntTask()
    {
        foreach (Task task in children)
        {
            yield return StartCorutine(task.RuntTask());
                    }
    }}
using UnityEngine;
using System.Collections;
public class Selector: Task{
    public override void SetResult(bool r)
     {
        if (r == true)
            isDone = true;
            }
    public override IEnumerator RuntTask()
    {
        foreach (Task task in children)
        {
            yield return StartCorutine(task.RuntTask());
           }}

往期回顾:

06.游戏AI方法之分层状态机

05.游戏AI方法之有限状态机

04.《吃豆人》的游戏AI分析