行为树(Behavior Trees)

行为树(Behavior Trees)是一种在游戏开发中广泛使用的AI设计模式,主要用于描述AI的行为和决策过程,实现更加智能和自然的游戏AI。它由多个节点组成,每个节点代表一个行为或决策,按照特定的方式连接在一起,形成一个树状结构。
在行为树中,根节点是AI的起点,通过遍历子节点来决策AI的行为。节点有以下三种状态:成功(Success)、失败(Failure)和运行(Running)。前两个通知其父节点其操作是成功还是失败。第三种意味着尚未确定成功或失败,并且该节点仍在运行。下次树被选择时,该节点将再次被选择,此时它将再次有机会成功,失败或继续运行。
行为树的节点有以下几种主要原型:

  1. 组合控制节点(Composite):一种将多个子节点组合在一起的节点,用于实现复杂的行为和决策逻辑。主要包括次序节点(Sequencer)和选择节点(Selector)。次序节点并行执行多个子节点,直到所有子节点都返回成功或者任意一个子节点返回失败为止。选择节点按照顺序执行子节点,当某个子节点返回成功时,停止执行并返回成功。
    在这里插入图片描述
    在这里插入图片描述

  2. 修饰节点(Decorator):一种特殊的节点,它不执行具体的行为或决策,而是修饰其它节点的行为或决策。主要包括逆变节点(Inverter)和重复节点(Repeater)。逆变节点可以将子节点的结果倒转,比如子节点返回了失败,则这个修饰节点会向上返回成功,以此类推。重复节点重复执行其子节点指定的次数或者一直重复执行,直到其子节点返回成功或者失败。
    在这里插入图片描述
    在这里插入图片描述

  3. 叶节点(Leaf):树的最末端,就是这些AI实际上去做事情的命令。

行为树通过模拟树状结构来描述AI的行为和决策过程,使得AI的行为更加灵活、自然和智能。
代码实现
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{public class BehaviourTree : MonoBehaviour{private Node root = null;private Blackboard blackboard;public Node Root{get{return root;}set{root= value;}}void Start(){Init();}void Update(){if(root!=null&& gameObject!=null){root.Evaluate(gameObject.transform,blackboard);}}protected virtual void Init(){blackboard = new Blackboard();}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{//行为树共享数据public class Blackboard{private Dictionary<string,object> Data;public Blackboard(){Data = new Dictionary<string, object>();}//获取数据public T Get<T>(string key){if(Data.ContainsKey(key)){return (T)Data[key];}return default;}//添加数据public void Add<T>(string key,T value){if(Data.ContainsKey(key)){Data[key] = value;}else{Data.Add(key,value);}}//删除数据public void Remove(string key){if(Data.ContainsKey(key)){Data.Remove(key);}else{Debug.Log("数据不存在 "+key);}}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{//状态类型public enum Status{Running,    //运行中Failure,    // 失败Success,    //成功}//节点基类public abstract class Node{protected Node parent;protected Status status;Status Status{get{return status;}set{status = value;}}public Node(){}//声明节点状态返回方法public abstract Status Evaluate(Transform transform,Blackboard blackboard);}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{//复合节点类public abstract class Composite : Node{//子节点列表protected List<Node> children = new List<Node>();protected int index;//子节点下标计数protected Composite(List<Node> children){index = 0;foreach(var child in children) {this.children.Add(child);}}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{//修饰器节点public abstract class Decorator : Node{//子节点列表protected List<Node> children;protected Decorator(List<Node> children){children = new List<Node>(){};foreach(var child in children) {this.children.Add(child);}}}}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{//选择节点,所有子节点都为失败则失败public class Selector : Composite{public Selector(List<Node> children) : base(children){}//所有子节点都为失败则失败public override Status Evaluate(Transform transform, Blackboard blackboard){if(index>=children.Count){index = 0;return Status.Success;}var status = children[index].Evaluate(transform,blackboard);switch(status){case Status.Success:index = 0;return Status.Success;case Status.Failure:index+=1;if(index>=children.Count){index = 0;return Status.Failure;}return Status.Running;case Status.Running:return Status.Running;default:return Status.Failure;}}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{//顺序节点,所有子节点成功才成功public class Sequencer : Composite{public Sequencer(List<Node> children) : base(children){}//所有子节点成功才成功public override Status Evaluate(Transform transform, Blackboard blackboard){if(index>=children.Count){index = 0;return Status.Success;}var status = children[index].Evaluate(transform,blackboard);switch(status){case Status.Success:index+=1;if(index>=children.Count){index = 0;return Status.Success;}return Status.Running;case Status.Failure:return Status.Failure;case Status.Running:return Status.Running;default:return Status.Failure;}}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{//任务节点,这里会处理对象具体行为逻辑(叶节点)public abstract class Task : Node{}
}

简单使用
实现敌人在两点之间巡逻,人物靠近会变红温并停止移动,人物远离时继续巡逻
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;
using System.ComponentModel.Design.Serialization;
using System.Linq;namespace BehaviourTree
{public class EnemyBT : BehaviourTree{Vector3 aPos = new Vector3(4.07999992f,-2.21000004f,-2);Vector3 bPos = new Vector3(4.07999992f,1.65999997f,-2)protected override void Init(){//调用基类初始化base.Init();//创建变红节点TurnRed turnRed = new TurnRed();//创建巡逻节点Patrol patrol = new Patrol(aPos,bPos);//创建查找节点FindObject findObject = new FindObject();//创建侦查节点子节点序列Node[] spyChildren = {findObject,turnRed};//创建顺序节点用于执行侦查行为EnemySequencer enemySequencer = new EnemySequencer(spyChildren.ToList());//创建根节点子节点序列Node[] selectorChildren = {enemySequencer,patrol};//创建选择节点用于处理侦查和巡逻行为EnemySelector enemySelector = new EnemySelector(selectorChildren.ToList());//将选择节点设置为根节点Root = enemySelector;}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{public class EnemySelector : Selector{public EnemySelector(List<Node> children) : base(children){}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;namespace BehaviourTree
{public class EnemySequencer : Sequencer{public EnemySequencer(List<Node> children) : base(children){}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;
using DG.Tweening;namespace BehaviourTree
{public class FindObject : Task{float radius = 5f;int layer = 512;public override Status Evaluate(Transform transform, Blackboard blackboard){Collider2D obj = Physics2D.OverlapCircle(transform.position,radius,layer);if(obj!=null){return Status.Success;   }transform.gameObject.GetComponent<SpriteRenderer>().DOColor(Color.white,1);return Status.Failure;}}
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;
using DG.Tweening;namespace BehaviourTree
{//在aPoint和bPoint之间来回移动public class Patrol : Task{Vector3 aPoint;Vector3 bPoint;float speed = 4f;Vector3 target;public Patrol(Vector3 aPos,Vector3 bPos){aPoint = aPos;bPoint = bPos;target = aPoint;}public override Status Evaluate(Transform transform, Blackboard blackboard){if(Vector2.Distance(transform.position,target)<0.1f){if(target == aPoint){target = bPoint;}else{target = aPoint;}}else{transform.position = Vector2.MoveTowards(transform.position,target,Time.deltaTime*speed);}return Status.Success;}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviourTree;
using DG.Tweening;namespace BehaviourTree
{//变红public class TurnRed : Task{Vector3 bPoint;public override Status Evaluate(Transform transform, Blackboard blackboard){transform.gameObject.GetComponent<SpriteRenderer>().DOColor(Color.red,1);return Status.Success;}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/626084.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#编程-自定义属性

命名自定义属性 让我们继续漏洞修复示例,在这个示例中新的自定义属性被命名为BugFixingAttribute。通常的约定是在属性名称后添加单词Attribute。编译器通过允许您调用具有短版名称的属性来支持附加。 因此,可以如以下代码段所示编写该属性: [ BugFixing ( 122,"Sara…

U-Boot学习(3):.config、defconfig文件对比及图形化配置Kconfig

在上一节中&#xff0c;我们介绍了U-Boot编译和.config配置文件生成分析&#xff0c;我们可以通过make xxx__defconfig来进行一些配置&#xff0c;其中xxx__defconfig对应config目录下的基于不同开发板的一些配置&#xff0c;指令执行完后会根据对应的配置在根目录下生成一个.c…

LLM之幻觉(二):大语言模型LLM幻觉缓减技术综述

LLM幻觉缓减技术分为两大主流&#xff0c;梯度方法和非梯度方法。梯度方法是指对基本LLM进行微调&#xff1b;而非梯度方法主要是在推理时使用Prompt工程技术。LLM幻觉缓减技术&#xff0c;如下图所示&#xff1a; LLM幻觉缓减技术值得注意的是&#xff1a; 检索增强生成&…

将Sqoop与Hive集成无缝的数据分析

将Sqoop与Hive集成是实现无缝数据分析的重要一步&#xff0c;它可以将关系型数据库中的数据导入到Hive中进行高级数据处理和查询。本文将深入探讨如何实现Sqoop与Hive的集成&#xff0c;并提供详细的示例代码和全面的内容&#xff0c;以帮助大家更好地了解和应用这一技术。 为…

bee工具的使用及创建第一个项目

前提文章&#xff1a;beego的安装及配置参数说明-CSDN博客 提示&#xff1a;beego框架下项目需要再GOPATH/src下进行开发&#xff0c;我的GOPATH是C:\Users\leell\go web项目创建 通过 bee new 创建web项目 C:\Users\leell\go\src>bee new beego-web 2024/01/15 21:40:0…

详细讲解Python连接Mysql的基本操作

目录 前言1. mysql.connector2. pymysql 前言 连接Mysql一般有几种方法&#xff0c;主要讲解mysql.connector以及pymysql的连接 后续如果用到其他库还会持续总结&#xff01; 对于数据库中的表格,本人设计如下:(为了配合下面的操作) 1. mysql.connector mysql.connector 是一…

自动化的自动化(1)--OPCUA2HTML5

现在的自动化工程师是令人沮丧的&#xff0c;他们努力地实现各个行业的自动化系统&#xff0c;自己却停留在敲键盘的手工劳作的阶段&#xff0c;该解放自己了。这就是“自动化实现自动化”的话题。 OPC 统一架构&#xff08;简称 OPC UA&#xff09;是现代工厂自动化中用于机器…

漏洞复现-Yearning front 任意文件读取漏洞(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…

身体互联网 (IoB)

现在&#xff0c;我们的互联网网关就是我们手中的一个小设备。 普渡大学副教授施里亚斯森表示。 我们不断地看着这个盒子&#xff0c;我们低着头走路&#xff0c;我们把大部分时间都花在它上面。如果我们不想让这种未来继续下去&#xff0c;我们就需要开发新技术。相反&#x…

#RAG##AIGC#检索增强生成 (RAG) 基本介绍和入门实操示例

本文包括RAG基本介绍和入门实操示例 RAG 基本介绍 通用语言模型可以进行微调以实现一些常见任务&#xff0c;例如情感分析和命名实体识别。这些任务通常不需要额外的背景知识。 对于更复杂和知识密集型的任务&#xff0c;可以构建基于语言模型的系统来访问外部知识源来完成任…

系统架构11 - 数据库基础(上)

数据库基础 数据库基本概念概述三级模式、两级映像概念模式外模式内模式二级映像逻辑独立性物理独立性 数据库设计需求分析概念结构设计逻辑结构设计物理设计数据库实施阶段据库运行和维护阶段 数据模型E-R模型关系模型模型转换E-R图的联系 关系代数 数据库基本概念 概述 数据…

openpyxl绘制图表

嘿&#xff0c;你是不是在处理Excel文件时感到束手无策&#xff1f;是不是想要一个简单而又强大的工具来处理数据分析和图表制作&#xff1f;别担心&#xff0c;我们有解决方案&#xff01;让我向你介绍openpyxl&#xff0c;这是一个Python库&#xff0c;专门用于处理Excel文件…

使用MDT将系统升级为Win10

创建升级到Win10任务序列 右键选择Task Sequence &#xff0c;然后选择NEW Task Sequence 填写ID name 默认配置 选择企业版 默认配置 填写组织 输入Administrator密码 点击下一步 等待完成 我们提前安装一台WIN7&#xff0c;并激活 选择打开 选择是 选择我们要创建好的升级win…

2.3 数据链路层03

2.3 数据链路层03 2.3.7 以太网交换机 1、以太网交换机的基本功能 以太网交换机是基于以太网传输数据的交换机&#xff0c;以太网交换机通常都有多个接口&#xff0c;每个接口都可以直接与一台主机或另一个以太网交换机相连&#xff0c;一般都工作在全双工方式。 以太网交换…

C程序技能:彩色输出

在终端上输出的字体总是单色&#xff0c;但在一些场景彩色输出更能满足需求&#xff0c;在Linux环境中&#xff0c;可以使用终端控制字符来设置输出字符的颜色&#xff0c;在部分版本的Windows系统中也可以使用。本文参考一些文献简要介绍一下在Windows下彩色输出的方法。 1. …

Rust-借用和生命周期

生命周期 一个变量的生命周期就是它从创建到销毁的整个过程。其实我们在前面已经注意到了这样的现象&#xff1a; 然而&#xff0c;如果一个变量永远只能有唯一一个入口可以访问的话&#xff0c;那就太难使用了。因此&#xff0c;所有权还可以借用。 借用 变量对其管理的内存…

从零开始:生产环境如何部署 Bytebase

Bytebase 是面向研发和 DBA 的数据库 DevOps 和 CI/CD 协同平台。目前 Bytebase 在全球类似开源项目中 GitHub Star 数排名第一且增长最快。 Bytebase 的架构 Bytebase 是一个单体架构 (monolith)&#xff0c;前端是 Vue3 TypeScript&#xff0c;后端是 Go。前端利用 Go 1.6 …

MySQL面试题 | 09.精选MySQL面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

linux下485通信调试记录

1、使用linux下使用串口调试助手 linux下可以安装并使用下述串口调试工具进行串口测试&#xff1a; 1.1、cutecom cutecom是linux下常用的图形化串口调试软件&#xff0c;通过以下命令安装并打开&#xff1a; sudo apt-get install cutecom sudo cutecom显示如下&#xff1…

【IPC通信--共享内存】

进程间通信目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享同样的资源。 通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xff09;发生了某种事件&#xff08;如…