AI之用行为树来实现逻辑

行为树是一种在游戏中常用的实现AI的方式,通过行为树可行图形化实现常用的程序结构。

一 行为树节点类型

每次执行AI时,从根节点(root)或running节点开始遍历,父节点执行子节点,子节点执行完后将结果返回父节点,父节点根据子节点的结果来决定接下来怎么做。行为树的执行过程就是查找要执行的叶子节点的过程,查找的依据就是先执行的叶子节点的结果。通常每个节点有三个状态:成功(success),失败(failure),执行中(running)。行为树的遍历实际上是一次函数调用,立即完成的,但是动作节点的执行确实一个过程,不能立即完成。这就导致动作节点在为完成之前会被多次执行,因此引入了running状态,用于表示节点正在执行,每次执行时,跳过之前已经执行完毕的节点,从上次未执行完毕的节点开始执行。但同时需要注意的是,running状态下AI不会遍历行为树,不能影响环境的变化,running节点必须是一个不可打断动作节点。

1 顺序节点(sequence)

组合节点(Composite),从左往右依次执行,类似逻辑与。
1.子节点返回failure,则停止执行,返回failure,下次从根节点开始执行;
2.子节点返回running,则停止执行,返回running,下次从running节点开始执行;
3.子节点返回success,则执行下一个节点,所有节点都返回success,则返回success,下次从根节点开始执行。

其伪代码流程如下:

def sequence_node(owner, node_name):
    run_index = get_run_index(node_name)
    while run_index < len(child_list):
        res = child_list[run_index](owner)
        if res == FAILURE:
            set_run_index(node_name, 0)
            return res
        elif res == RUNNING:
            set_run_index(node_name, run_index)
            return res
        else:
            run_index += 1
    set_run_index(node_name, 0)
    return SUCCESS

2 选择节点(selector)

组合节点(Composite),从左往右依次执行,类似逻辑与。
1.子节点返回success,则停止执行,返回success,下次从根节点开始执行;
2.子节点返回running,则停止执行,返回running,下次从running节点开始执行;
3.子节点返回failure,则执行下一个节点,所有节点都返回failure,则返回failure,下次从根节点开始执行。

其伪代码流程如下:

def selector_node(owner, node_name):
    run_index = get_run_index(node_name)
    while run_index < len(child_list):
        res = child_list[run_index](owner)
        if res == SUCCESS:
            set_run_index(node_name, 0)
        elif res == RUNNING:
            set_run_index(node_name, run_index)
        else:
            run_index += 1
    set_run_index(node_name, 0)
    return FAILURE

3 并行节点(parallel)

组合节点(Composite),会依次执行其全部子节点,然后根据所有子节点的返回值,指定该节点的返回值。
其伪代码流程如下:

def parallel(owner, node_name):
    run_index_list = get_run_index(node_name)
    if len(run_index_list) > 0:
        for index in run_index_list:
            state_dic[index] = child_list[index](owner)
    else:
        run_index = 0
        while run_index < len(child_list):
            state_dic[run_index] = child_list[run_index](owner)
            run_index += 1
    if state_dic.count(SUCCESS) >= MIN_SUCCESS:
        return SUCCESS
    elif state_dic.count(FAILURE) >= MIN_FAILURE:
        return FAILURE
    else:
        return RUNNING

4 概率节点(probability)

组合节点,根据填写的概率权重,随机执行其一个子节点。

其伪代码流程如下:

def probability(owner, node_name):
    run_index = get_run_index(node_name)
    if get_exe_state(node_name) == STATE_NO_RUNNING:
        weight = random.uniform(0, total_weight)
        run_index = 0
        for i, w in enumerate(weights):
            if weight < w:
                run_index = i
                break
            else:
                weight -= w
    res = child_list[run_index](owner)
    if res == RUNNING:
        set_run_index(node_name, run_index)
        set_exe_state(node_name, STATE_RUNNING)
    else:
        set_run_index(node_name, 0)
        set_exe_state(node_name, STATE_NO_RUNNING)
    return res

5 装饰节点(decorator)

中间节点,对子节点的返回值做相应的装饰,因此一定会有一个子节点。

6 条件节点(condition)

叶子节点(Leaf)
条件成立返回success,失败返回failure。

7 动作节点(acation)

叶子节点(Leaf)
返回success

组合节点都有行为树的解析器实现,使用者需要自己实现的是叶子节点。

二 实现逻辑结构

下面使用行为树节来实现一个怪物的AI,来演示各逻辑结构如何实现。

1 顺序

顺序逻辑结构推挤用顺序节点实现,每个子节点都是动作节点。
假设,要实现的AI,先查找目标,然后攻击。

AI之用行为树来实现逻辑_第1张图片

2 选择

if结构:
假设,要实现的AI,如果发现目标,则进行攻击。

AI之用行为树来实现逻辑_第2张图片

if-else结构:
例如,要实现的AI,如果发现目标,则进行攻击,否则巡逻。

AI之用行为树来实现逻辑_第3张图片

if-elseif结构:
例如,要实现的AI,如果发现目标,则进行攻击,如果发现掉落装备,则捡装备,否则巡逻。

AI之用行为树来实现逻辑_第4张图片

3 循环

例如,要实现的AI,如果发现目标,则进行攻击,如果发现掉落装备,则捡装备,否则巡逻。
捡装备的过程是,移动到装备所在位置,然后捡装备。

AI之用行为树来实现逻辑_第5张图片

在移动到装备位置的过程中,此节点返回running,直达移动到该点,才返回success。在此过程中,循环的执行该节点,判断是否移动到了指定位置。

你可能感兴趣的:(游戏开发)