教程1:Hello Behaviac
https://www.behaviac.com/tutorial_1_hello_behaviac/
编辑器的使用
新建工作区
工作区用于管理整个项目的配置,包括一些位置和语言等参数。
打开编辑器,点击菜单项“文件”->“新建工作区”,弹出新建工作区窗口,如下图所示:
- 工作区位置:保存工作区文件的目录,在该目录下会保存出*.workspace.xml的文件,该文件即是编辑器打开的工作区文件(或者称之为项目文件)。
- 行为树源位置:对既有服务器,又有客户端的项目开发,可能需要共用行为树,这时候只要为服务器和客户端分别创建工作区,然后为它们设置相同的“行为树源位置”即可。这样,只需要编辑同一份行为树,就可以让服务器和客户端的AI逻辑保持一致。此外,源位置中还自动生成behaviac_meta文件夹,里面保存了跟工作区同名但后缀名为*.meta.xml的类型信息文件。
- 行为树导出位置:在该目录下,导出编辑好的行为树,并且需要在程序端设置的加载位置,以便程序运行起来后,加载所需的行为树。
- 代码生成位置:用于存放后面将要描述的类型信息浏览器中编辑好的类型代码文件,还包含了一些“胶水”代码文件,都需要整合到运行时(游戏端)一起编译构建。
- 程序端开发语言:可选cpp(即C++)和cs(即C#)两种,表示程序端的代码语言。结合上面所说的情况,可以支持服务器和客户端采用不同的语言编写代码,但共用同一份行为树数据。
“胶水”代码:是指编辑器自动生成的代码文件,用于注册类型信息,并用于程序端执行时通过名字或ID调用类的成员属性或方法。
点击确认后,就可以创建自己的工作区。创建完工作区之后,后续如果需要修改工作区中的参数,可以通过菜单项“文件”->“编辑工作区”,重新打开上图所示的窗口来修改相关的参数。
另外,还可以直接打开为本教程建好的工作区。点击菜单项“文件”->“打开工作区”,找到安装或源码包目录中的tutorials/tutorial_1/workspace文件夹,打开tutorial_1_cpp.workspace.xml文件,如下图所示:
编辑类型信息
为了让行为树可以描述某个Agent类型的行为,首先需要创建自己的Agent子类。
通过菜单项“视图”->“类型信息”(或快捷键Ctrl+M),打开类型信息浏览器,可以看到当前类型列表中只有一个默认生成的behaviac::Agent基类,如下图所示:
点击右上角的“新增”按钮,弹出“新增类型”窗口,如下图所示:
- 将“类型”选择为“Agent”
- 将“名称”设置为“FirstAgent”
- 右上方的“生成代码?”默认是勾选上的,表示编辑器要自动生成该类型的代码文件,否则该类型代码需要手工编写
- “生成位置”是生成该类型文件所在的文件夹,默认不用设置,表示默认生成在工作区中配置的“代码生成位置”里面
点击“确定”按钮后,可以看到类型列表中有了“FirstAgent”这个类,如下图所示:
选中该“FirstAgent”类,并设置中部的 “成员类型”为“Method”,可以看到目前该类有六个来自behaviac::Agent基类的成员方法,方法名前面的“~”表示该方法是从基类继承过来的,如上图所示。
点击右侧的“新增”按钮,弹出“新增方法”窗口,如下图所示:
将新方法的“名字”设为“SayHello”,其他参数暂不用设置。
直接点击“确定”按钮,回到类型信息浏览器,可以看到“FirstAgent”类有了第一个自己添加的成员方法“SayHello”,其他几个带“~”的方法表示是从基类继承过来的成员方法,如下图所示:
现在,我们有了第一个Agent子类的“FirstAgent”,以及它的成员方法“SayHello”。
点击右下方的“应用”按钮,自动生成类型和其他相关的“胶水”代码文件等。
点击左下方的“打开代码生成位置”按钮,可以查看生成的代码文件,如下图所示:
其中,behaviac_types.h需要包含到自己的代码中,以便使用自动生成的类型和“胶水”代码,如下代码所示:
#include "behaviac_generated/types/behaviac_types.h"
“internal”文件夹中包含了前面提及的类型和“胶水”代码,如下图所示:
其中,behaviac_agent_member_visitor.h文件生成了用于访问类的私有属性和方法的“胶水”代码,behaviac_agent_meta.h/cpp文件生成了用于注册类及其属性、方法、实例等信息的“胶水”代码,这些“胶水”代码主要是为了程序端可以通过名字自动取用到类及其成员属性、方法及其实例等。
这些生成的代码需要添加到自己的项目中一起编译构建,如下图所示:
创建行为树
有了上面创建的Agent子类“FirstAgent”后,就可以开始创建和编辑行为树了。
如果对编辑器的按键操作不熟悉,请通过菜单项“帮助”->“起始页”,查看按键说明,如下图所示:
点击工具栏中的“新建行为树”按钮,如下图所示:
新建行为树后,将该行为树名字改为“FirstBT”,现在有了第一棵行为树,该树只有一个根节点,如下图所示:
鼠标左键单击选中该根节点,为该节点的“Agent类型”设置为前面创建的“FirstAgent”,表示这棵行为树用来描述FirstAgent类的行为,如下图所示:
设置完后,可以发现根节点已经具有类型“FirstAgent”,如下图所示:
在左侧的节点列表中(如下图所示),用鼠标左键选中“动作”节点(或其他需要的节点)后,按住鼠标左键并拖拽该节点到右侧的主视口中,并将动作节点落在根节点右侧的黑色三角箭头处。
拖拽完毕,可以看到行为树有了叶子节点“动作”,如下图所示:
选中该动作节点,在右侧“动作的属性”窗口中,为其选择成员方法“SayHello”,并将另一参数“决定状态的选项”设置为“Success”,如下图所示:
如果想了解动作节点的更多细节,请参考文档《动作节点》。或者选中某个节点后,按F1键或右键菜单直接打开该节点的文档。
至此,我们得到了一棵最简单但是完整的行为树,如下图所示:
导出行为树
编辑完行为树后,需要导出全部行为树,以便程序端加载使用。
点击工具栏中的“导出全部”按钮,如下图所示:
弹出“导出”窗口,在导出格式中暂只用勾选“Xml”,点击右下方的“导出”按钮,如下图所示:
导出后,打开工作区中指定的导出目录,可以看到成功导出了FirstBT.xml文件和meta文件夹中的tutorial_1_cpp.meta.xml文件,如下图所示:
导出的FirstBT.xml文件就是交给程序端加载使用的行为树,tutorial_1_cpp.meta.xml文件是交给程序端加载使用的含有类型和自定义成员属性信息的文件。
注意:下面不管是C#还是C++或者在unity里面都是共通的
首先,在InitBehaviac()方法中初始化behaviac的加载目录和文件格式等,如下代码所示:
C++:
bool InitBehavic()
{LOGI("InitBehavic\n");behaviac::Workspace::GetInstance()->SetFilePath("../tutorials/tutorial_1/cpp/exported");behaviac::Workspace::GetInstance()->SetFileFormat(behaviac::Workspace::EFF_xml);return true;
}
上面的几个接口说明如下:
- Workspace::SetFilePath()用于设置加载编辑器导出的行为树所在的目录。
- Workspace::SetFileFormat()用于设置加载的行为树格式,这里用的是xml格式。
接着,创建Agent子类“FirstAgent”的实例,并加载指定的行为树,这里的行为树名字为“FirstBT”,如下代码所示:
bool InitPlayer()
{LOGI("InitPlayer\n");g_FirstAgent = behaviac::Agent::Create<FirstAgent>();bool bRet = g_FirstAgent->btload("FirstBT");g_FirstAgent->btsetcurrent("FirstBT");return bRet;
}
上面的几个接口说明如下:
- Agent::Create()用于创建Agent子类的实例。
- Agent::btload()用于加载行为树,入口参数是行为树的名字,不要加后缀。
- Agent::btsetcurrent()用于指定当前准备执行的行为树。
其次,开始执行行为树,如下代码所示:
void UpdateLoop()
{LOGI("UpdateLoop\n");int frames = 0;behaviac::EBTStatus status = behaviac::BT_RUNNING;while (status == behaviac::BT_RUNNING){LOGI("frame %d\n", ++frames);status = g_FirstAgent->btexec();}
}
Agent::btexec()用于执行一次前面通过Agent::btsetcurrent()指定的行为树。
另外,如果不通过Agent::btexec()来单独执行行为树,也可以调用Workspace::Update()的方式来统一执行所有Agent实例的行为树,详见文章《运行时端的执行流程》。
然后,对创建的Agent实例进行销毁释放,并清理整个工作区,如下代码所示:
void CleanupPlayer()
{LOGI("CleanupPlayer\n");behaviac::Agent::Destroy(g_FirstAgent);
}void CleanupBehaviac()
{LOGI("CleanupBehaviac\n");behaviac::Workspace::GetInstance()->Cleanup();
}
最后,打开FirstAgent.cpp文件,并修改FirstAgent::SayHello()方法如下:
///<<< THE METHOD HEAD
void FirstAgent::SayHello()
{///<<< BEGIN WRITING YOUR CODEprintf("\nHello Behaviac!\n\n");///<<< END WRITING YOUR CODE
}
注意:自己的代码需要添加在“///<<< BEGIN WRITING YOUR CODE”和“///<<< END WRITING YOUR CODE”之间,以便编辑器下次生成代码的时候,可以自动合并手工添加的内容和生成的内容。
编译并运行整个程序,执行结果如下:
Unity C#版
打开Unity编辑器创建一个空的Unity项目,保存该项目,或者直接打开安装目录下的tutorials/tutorial_1/unity目录中的项目。
通过behaviac编辑器创建一个工作区(或者直接打开安装包目录下的Unity工作区文件tutorials/tutorial_1/workspace/tutorial_1_unity.workspace.xml),相关参数配置如下图所示:
添加FirstAgent类及其成员方法SayHello()、创建和导出行为树FirstBT等流程跟上文相同。
导出整个工作区后,可以看到在目录tutorials\tutorial_1\unity\Assets\Scripts\behaviac\behaviac_generated\types有了自动生成的源码文件,如下图所示:
在Unity编辑器中导入安装包目录下的behaviac运行时包integration/behaviac***.unitypackage。
打开整个项目的源码工程,可以看到有了behaviac的运行时库runtime和编辑器生成的源码behaviac_generated,如下图所示:
打开FirstAgent.cs文件,添加代码如下:
首先,在InitBehaviac()方法中初始化behaviac的加载目录和文件格式等,如下代码所示:
private static string ExportedFilePath
{get{string relativePath = "/Resources/behaviac/exported";if (Application.platform == RuntimePlatform.WindowsEditor) {return Application.dataPath + relativePath;}else if (Application.platform == RuntimePlatform.WindowsPlayer) {return Application.dataPath + relativePath;}else {return "Assets" + relativePath;}}
}private bool InitBehavic()
{behaviac.Debug.LogWarning("InitBehavic");behaviac.Workspace.Instance.FilePath = ExportedFilePath;behaviac.Workspace.Instance.FileFormat = behaviac.Workspace.EFileFormat.EFF_xml;return true;
}
接着,加载指定的行为树,这里的行为树名字为“FirstBT”,如下代码所示:
private bool InitPlayer()
{behaviac.Debug.LogWarning("InitPlayer");bool bRet = this.btload("FirstBT");if (bRet){this.btsetcurrent("FirstBT");}return bRet;
}
在Awake()方法中调用InitBehavic和InitPlayer方法,如下代码所示:
void Awake()
{InitBehavic();InitPlayer();
}
其次,在Update()方法中执行行为树,如下代码所示:
behaviac.EBTStatus _status = behaviac.EBTStatus.BT_RUNNING;void Update()
{if (_status == behaviac.EBTStatus.BT_RUNNING){behaviac.Debug.LogWarning("Update");_status = this.btexec();}
}
然后,修改SayHello()方法如下:
public void SayHello()
{///<<< BEGIN WRITING YOUR CODE SayHellobehaviac.Debug.LogWarning("Hello Behaviac!");///<<< END WRITING YOUR CODE
}
注意:自己的代码需要添加在“///<<< BEGIN WRITING YOUR CODE”和“///<<< END WRITING YOUR CODE”之间,以便编辑器下次生成代码的时候,可以自动合并手工添加的内容和生成的内容。
最后,在Unity编辑器中添加一个GameObject,并且为其添加脚本组件FirstAgent,如下图所示:
在Unity编辑器中运行这个简单的程序,执行结果如下:
下载源码包后,通过Unity编辑器打开并运行tutorials/tutorial_1/unity目录中的项目,就可以看到上图的结果。
本教程相关的工作区和代码工程详见源码包的目录tutorials/tutorial_1。
教程1:Hello Behaviac相关推荐
- 使用Docker搭建svn服务器教程
使用Docker搭建svn服务器教程 svn简介 SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS.互联网上很 ...
- mysql修改校对集_MySQL 教程之校对集问题
本篇文章主要给大家介绍mysql中的校对集问题,希望对需要的朋友有所帮助! 推荐参考教程:<mysql教程> 校对集问题 校对集,其实就是数据的比较方式. 校对集,共有三种,分别为:_bi ...
- mysql备份psb文件怎么打开_Navicat for MySQL 数据备份教程
原标题:Navicat for MySQL 数据备份教程 一个安全和可靠的服务器与定期运行备份有密切的关系,因为错误有可能随时发生,由攻击.硬件故障.人为错误.电力中断等都会照成数据丢失.备份功能为防 ...
- php rabbmq教程_RabbitMQ+PHP 教程一(Hello World)
介绍 RabbitMQ是一个消息代理器:它接受和转发消息.你可以把它当作一个邮局:当你把邮件放在信箱里时,你可以肯定邮差先生最终会把邮件送到你的收件人那里.在这个比喻中,RabbitMQ就是这里的邮箱 ...
- 【置顶】利用 NLP 技术做简单数据可视化分析教程(实战)
置顶 本人决定将过去一段时间在公司以及日常生活中关于自然语言处理的相关技术积累,将在gitbook做一个简单分享,内容应该会很丰富,希望对你有所帮助,欢迎大家支持. 内容介绍如下 你是否曾经在租房时因 ...
- Google Colab 免费GPU服务器使用教程 挂载云端硬盘
一.前言 二.Google Colab特征 三.开始使用 3.1在谷歌云盘上创建文件夹 3.2创建Colaboratory 3.3创建完成 四.设置GPU运行 五.运行.py文件 5.1安装必要库 5 ...
- 理解和实现分布式TensorFlow集群完整教程
手把手教你搭建分布式集群,进入生产环境的TensorFlow 分布式TensorFlow简介 前一篇<分布式TensorFlow集群local server使用详解>我们介绍了分布式Ten ...
- 高级教程: 作出动态决策和 Bi-LSTM CRF 重点
https://www.zhihu.com/question/35866596 条件随机场 CRF(条件随机场)与Viterbi(维特比)算法原理详解 https://blog.csdn.net/qq ...
- PyTorch 高级实战教程:基于 BI-LSTM CRF 实现命名实体识别和中文分词
20210607 https://blog.csdn.net/u011828281/article/details/81171066 前言:译者实测 PyTorch 代码非常简洁易懂,只需要将中文分词 ...
最新文章
- 学python需要英语基础吗-学python需要英语基础吗
- java 布局教程_java布局学习(新)
- 英伟达新禁令:不能随便用GeForce显卡跑深度学习(挖矿可以)
- Android Studio 编译失败 Could not read entry ':app:processDebugManifest' from cache taskArtifacts.bin
- Icon资源详解[1]
- 地图标识符号大全_资源小结:旅游类地图汇总(8.17版)
- 解决从PDF复制到Word中的英文字母变成宋体格式的问题
- Spring学习(全)
- USB Server应用于税控盘的远程集中管理
- 【第三方互联】2、创建腾讯QQ互联应用
- SQL IF语句的使用
- 读数学建模国赛优秀论文的笔记
- Uber 叫车时,弹出以下代码导致无法打车(An email confirmation has been sent to...),解决办法...
- RF Python扩展测试库
- asterisk拨号规则
- Head First java 上的报错!
- 路由器交换机设备管理
- 合肥工业大学宣城校区2020年-2021年第一(大四上)学期物联网工程专业资料汇总(含课件、个人实验报告、实验代码、课设报告等)
- android 图片运动轨迹,基于Android的高德地图的定位和运动轨迹记录的功能
- 数学建模——评价算法
热门文章
- 元祖字典 java_元祖和字典
- selenium 淘宝登陆购买,基础实现
- 万分之二用百分之怎么表示_万分之一符号怎么写
- wireshark分析oracle报错,Linux下抓包工具tcpdump以及分析包的工具wireshark
- 艾宾浩斯遗忘曲线PHP,2018考研作文_艾宾浩斯遗忘曲线——记忆与复习_沪江英语...
- 和数软件新增6项计算机软件著作权登记证书
- 2020-mac-东芝的移动硬盘插入到我的macbook pro系统上没反应,只是等在闪烁
- 微信第三方服务平台源码分析——每个Action与模块的对应关系
- Linux部署IPFS(分布式存储系统)私有网络
- cup过高是什么意思_CPU占用过高怎么办? 每日一答