<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>文档 &#8211; behaviac</title>
	<atom:link href="/language/zh/category/docs/feed/" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>Tencent behaviac, Game AI, Behavior Tree, Finite State Machine, Hierarchical Task Network, BT FSM HTN, 腾讯开源, 游戏AI, 行为树,有限状态机,分层任务网络</description>
	<lastBuildDate>Tue, 25 Jul 2017 03:06:50 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.4.1</generator>
	<item>
		<title>节点类型的简单介绍</title>
		<link>/intro/</link>
					<comments>/intro/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Wed, 11 May 2016 10:05:17 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=216</guid>

					<description><![CDATA[behaviac 有以下节点类型： 其中‘附件’有前置和后置，可以添加到任何一个节点作为前置和后置。前置往往是作为前提条件（precondition）来使用，而<a class="moretag" href="/intro/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>behaviac 有以下节点类型：</p>
<p><img src="/img/references/nodetypes.png" alt="nodetypes" /></p>
<p>其中‘附件’有前置和后置，可以添加到任何一个节点作为前置和后置。前置往往是作为前提条件（precondition）来使用，而后置往往是当节点结束的时候施加效果（effects）。</p>
<p><img src="/img/references/prepost.png" alt="prepost" /></p>
<p>其中‘组合’，‘装饰器’ 类都是分支节点，‘动作’ 类，和‘条件’类大都是子节点， 而‘条件’类中的‘或’、‘与’是分支节点。</p>
<p>需要指出的是，有些节点类型通过其他更基本类型的节点的组合也可以实现。这里提供的节点类型只是使用起来可能会更方便，更直观些。用户可以根据自己的偏好选择使用与否。 用户也可以选择扩展节点类型提供扩展功能或者快捷方式，请参考‘教程’ 中的相关章节。 同时如果根本不打算使用某些节点类型，可以在 config.xml 里配置后就不会出现在可选的列表里了，请参考配置Config.xml。</p>
]]></content:encoded>
					
					<wfw:commentRss>/intro/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>原理和流程</title>
		<link>/workflow/</link>
					<comments>/workflow/#comments</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Mon, 16 Jan 2017 07:38:46 +0000</pubDate>
				<category><![CDATA[文章]]></category>
		<guid isPermaLink="false">/?p=1456</guid>

					<description><![CDATA[本文档有视频和文字说明。两者内容是一致的，以便您按需查看。 本文档描述的是3.6及以后版本。对于3.5及以前的老版本请参考分类“3.5”。 behaviac整套<a class="moretag" href="/workflow/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档有视频和文字说明。两者内容是一致的，以便您按需查看。
本文档描述的是3.6及以后版本。对于3.5及以前的老版本请参考分类“3.5”。</pre>
<h2 align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_0.mp4" controls="controls" width="640" height="480" data-mce-fragment="1"></video></h2>
<p style="text-align: left;" align="center">behaviac整套组件分为编辑器和运行时库，编辑器是独立运行的程序，运行时库需要整合到自己的项目中，各模块的关系如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1406" src="/wp-content/uploads/2016/12/architecture-2.png" sizes="(max-width: 687px) 100vw, 687px" srcset="/wp-content/uploads/2016/12/architecture-2.png 687w, /wp-content/uploads/2016/12/architecture-2-300x263.png 300w" alt="architecture" width="687" height="603" /></p>
<ul>
<li>工作区用于管理整个项目，包括类型信息和行为树文件等</li>
<li>类型信息包括Agent类及其成员属性、成员方法和实例等，以及枚举和结构体类型</li>
<li>行为树描述了指定的Agent类型的行为，利用各种节点和类型信息来创建行为树</li>
<li>运行时端根据编辑器导出的类型信息，执行导出的行为树</li>
</ul>
<p>整个组件的工作流程如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1404" src="/wp-content/uploads/2016/12/workflow-2.png" sizes="(max-width: 872px) 100vw, 872px" srcset="/wp-content/uploads/2016/12/workflow-2.png 872w, /wp-content/uploads/2016/12/workflow-2-300x225.png 300w, /wp-content/uploads/2016/12/workflow-2-768x577.png 768w" alt="workflow" width="872" height="655" /></p>
<pre>“胶水”代码：是指编辑器自动生成的代码文件，用于注册类型信息，可用于程序端执行时通过名字或ID调用类的成员属性或方法。</pre>
]]></content:encoded>
					
					<wfw:commentRss>/workflow/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>behaviac到底是什么</title>
		<link>/what_is_behaviac/</link>
					<comments>/what_is_behaviac/#respond</comments>
		
		<dc:creator><![CDATA[jonygli]]></dc:creator>
		<pubDate>Mon, 11 Apr 2016 10:02:27 +0000</pubDate>
				<category><![CDATA[文章]]></category>
		<category><![CDATA[概念]]></category>
		<guid isPermaLink="false">/?p=170</guid>

					<description><![CDATA[简述 behaviac是游戏AI的开发框架组件，也是游戏原型的快速设计工具。支持全平台，适用于客户端和服务器，助力游戏快速迭代开发 。 编辑器可以运行在PC上，<a class="moretag" href="/what_is_behaviac/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<h2 id="section"><span class="ez-toc-section" id="i">简述</span></h2>
<p>behaviac是游戏AI的开发框架组件，也是游戏原型的快速设计工具。支持全平台，适用于客户端和服务器，助力游戏快速迭代开发 。</p>
<p>编辑器可以运行在PC上，操作方便直观可靠，支持实时和离线调试；编辑器可以导出xml，bson等多种格式，更可以导出C++、C#源码，提供最高效率。</p>
<p>运行时支持全平台，有C++和C#两个版本，原生支持Unity。</p>
<p>已被多款知名游戏及更多其他预研项目使用。</p>
<p>所有代码，包括编辑器和运行时<a href="https://github.com/Tencent/behaviac">全部开源https://github.com/Tencent/behaviac</a></p>
<h2 id="section-1"><span class="ez-toc-section" id="i-2">编辑器和运行时</span></h2>
<p>behaviac作为游戏AI的开发框架组件，有编辑器和运行时两个部分，这两个部分通过类型信息（描述AI实例属性和能力方法的信息）交换信息。<br />
<img class="aligncenter size-full wp-image-1406" src="/wp-content/uploads/2016/12/architecture-2.png" alt="" width="687" height="603" srcset="/wp-content/uploads/2016/12/architecture-2.png 687w, /wp-content/uploads/2016/12/architecture-2-300x263.png 300w" sizes="(max-width: 687px) 100vw, 687px" /></p>
<h3 id="section-2"><span class="ez-toc-section" id="i-3">类型信息</span></h3>
<p>类型信息用来描述类型的属性和方法。在3.5及之前的旧版本通过运行时端导出类型信息，3.6及之后的新版本通过编辑器创建类型信息，如下所示。编辑器中，该类型信息作为基本的语法单位用来创建行为树。</p>
<pre class="brush: cpp; title: ; notranslate">&lt;agent classfullname=&quot;framework::GameObject&quot; base=&quot;behaviac::Agent&quot; inherited=&quot;true&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; IsRefType=&quot;true&quot;&gt;
&lt;Member Name=&quot;HP&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Type=&quot;uint&quot; Class=&quot;framework::GameObject&quot; /&gt;
&lt;Member Name=&quot;age&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Type=&quot;long&quot; Class=&quot;framework::GameObject&quot; /&gt;
&lt;Method Name=&quot;GoStraight&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Class=&quot;framework::GameObject&quot; ReturnType=&quot;void&quot;&gt;
&lt;Param DisplayName=&quot;speed&quot; Desc=&quot;speed&quot; Type=&quot;int&quot; /&gt;
&lt;/Method&gt;
&lt;Method Name=&quot;TurnTowardsTarget&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Class=&quot;framework::GameObject&quot; ReturnType=&quot;int&quot;&gt;
&lt;Param DisplayName=&quot;turnSpeed&quot; Desc=&quot;turnSpeed&quot; Type=&quot;float&quot; /&gt;
&lt;/Method&gt;
&lt;Method Name=&quot;alignedWithPlayer&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Class=&quot;framework::GameObject&quot; ReturnType=&quot;bool&quot; /&gt;
&lt;Method Name=&quot;playerIsAligned&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Class=&quot;framework::GameObject&quot; ReturnType=&quot;bool&quot; /&gt;
&lt;Method Name=&quot;projectileNearby&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Class=&quot;framework::GameObject&quot; ReturnType=&quot;bool&quot;&gt;
&lt;Param DisplayName=&quot;radius&quot; Desc=&quot;radius&quot; Type=&quot;float&quot; /&gt;
&lt;/Method&gt;
&lt;Method Name=&quot;distanceToPlayer&quot; DisplayName=&quot;&quot; Desc=&quot;&quot; Class=&quot;framework::GameObject&quot; ReturnType=&quot;float&quot; /&gt;
&lt;/agent&gt;</pre>
<p>在3.x版本之前的版本中，类型信息必须通过运行时来导出，策划需要新的属性或方法时，必须等待程序员更新代码重现导出类型信息后才能使用。而在3.x版本中，可以直接在编辑器中创建一个类型，并且创建它的属性和方法，而且可以导出类型的c++或c#源码，这极大的加速了迭代的过程，从而把编辑器作为一个原型设计工具。</p>
<h3 id="section-3"><span class="ez-toc-section" id="i-4">编辑器</span></h3>
<p>编辑器是一个可以运行在Windows平台上的编辑工具。<br />
<img src="/img/whatisbehaviac/designer.png" alt="designer" /><br />
在编辑器内，使用鼠标或快捷键，可以添加、编辑、配置、修改行为树（包括FSM，或HTN），也可以实时或离线调试游戏的行为，既可以设断点，也可以查看或修改变量的值。</p>
<h3 id="section-4"><span class="ez-toc-section" id="i-5">运行时</span></h3>
<p>运行时有C++和C#两个版本，Unity使用C#的实现，像是cocos等使用C++的引擎或平台使用C++的实现。其具体逻辑是一致的，即加载编辑器中导出的行为树，解释运行之。</p>
<pre class="brush: cpp; title: ; notranslate">

g_player = behaviac::Agent::Create&lt;CBTPlayer&gt;();

bool bRet = false;
bRet = g_player-&gt;btload(pszTreeName);
assert(bRet);

g_player-&gt;btsetcurrent(pszTreeName);

behaviac::EBTStatus status = behaviac::BT_RUNNING;

while (status == behaviac::BT_RUNNING)
{
status = g_player-&gt;btexec();
}</pre>
<div class="highlighter-rouge"></div>
<h3 id="section-5"><span class="ez-toc-section" id="i-6">导出和调试</span></h3>
<p>在编辑器内创建好行为后，需要导出，然后运行时才可以加载运行。编辑器支持导出多种格式：</p>
<ol>
<li>xml</li>
<li>bson</li>
<li>cpp</li>
<li>c#</li>
</ol>
<p>其中xml和bson作为数据，可以被加载，而cpp或c#作为源码直接编辑链接进程序，用户可以根据需要选择使用最合适的格式。</p>
<h2 id="behaviac"><span class="ez-toc-section" id="behaviac">behaviac能解决什么问题</span></h2>
<ul>
<li>behaviac作为游戏AI的开发框架组件，主要是用来开发游戏AI。</li>
<li>behaviac的编辑器使用图形化的界面（Visual scripting）和操作，操作直观方便。</li>
<li>游戏中的NPC，小怪，老怪等等的游戏逻辑都可以通过behaviac来创建和开发。</li>
<li>behaviac并不限于开发游戏AI的游戏逻辑，也可以用来开发组队逻辑（Squad Logic），策略AI（Strategy AI），玩家Avatar，甚至关卡设计等各种游戏场景。</li>
<li>behaviac还可以用作原型设计工具，策划只是使用behaviac编辑器来设计类型安全的，表达严谨的游戏逻辑。</li>
<li>C#版本的运行时原生支持unity，behaviac可以在unity内开发游戏AI</li>
<li>在iOS平台，作为热更新的一种手段</li>
<li>C++版本支持全平台，不仅可以用在客户端，也可以用在服务器端。一套逻辑，可以根据情况分别在客户端，服务器运行，避免重复开发。</li>
</ul>
<h2 id="behaviac-1"><span class="ez-toc-section" id="behaviac-2">behaviac有哪些主要特性</span></h2>
<ul>
<li>behaviac是游戏AI的开发框架组件，也是游戏原型的快速设计工具</li>
<li>支持持行为树（BT），状态机（FSM），层次任务网络（HTN）等多种范式</li>
<li>编辑器可以运行在PC上，操作方便直观可靠</li>
<li>编辑器可以导出xml，bson等多种格式，更可以导出C++，C#源码，提供最高效率</li>
<li>支持实时和离线调试，可以设断点，查看或修改变量</li>
<li>编辑器通过socket和游戏连接实现实时调试，支持远程实时调试</li>
<li>运行时支持全平台（Windows/Linux/iOS/Android等），有C++和C#两个版本，原生支持Unity。适用于客户端和服务器，助力游戏快速迭代开发</li>
<li>支持热加载，可以不用重启游戏就更新行为树</li>
<li>中英文界面可选，类型信息可以提供中英文显示信息</li>
<li>支持预制件（Prefab）、子树，方便重用共享</li>
<li>支持自定义数据类型，支持已有第3方库中的自定义类型</li>
<li>支持扩展节点类型</li>
</ul>
<hr />
<p><a href="/docs/zh/articles/overview/">可以继续阅读behaviac概述 →</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/what_is_behaviac/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程1：Hello Behaviac</title>
		<link>/tutorial_1_hello_behaviac/</link>
					<comments>/tutorial_1_hello_behaviac/#comments</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Tue, 20 Dec 2016 02:36:53 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1315</guid>

					<description><![CDATA[还未查看过文档《原理和流程》的请首先阅读该文档，以便了解behaviac组件的基本原理和工作流程。 本文档有视频和文字说明。两者内容是一致的，以便按需查看。 本<a class="moretag" href="/tutorial_1_hello_behaviac/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre style="text-align: left;">还未查看过文档《<a href="/workflow/">原理和流程</a>》的请首先阅读该文档，以便了解behaviac组件的基本原理和工作流程。

本文档有视频和文字说明。两者内容是一致的，以便按需查看。
本文档描述的是3.6及以后版本。对于3.5及以前的老版本请参考分类“3.5”。</pre>
<h2><span class="ez-toc-section" id="i">编辑器的使用</span></h2>
<h3><span class="ez-toc-section" id="i-2">新建工作区</span></h3>
<p>工作区用于管理整个项目的配置，包括一些位置和语言等参数。</p>
<h4><span class="ez-toc-section" id="i-3">视频</span></h4>
<p align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_1_0.mp4" controls="controls" width="640" height="480"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p>打开编辑器，点击菜单项“文件”-&gt;“新建工作区”，弹出新建工作区窗口，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1569" src="/wp-content/uploads/2016/12/tutorial_1_cpp_workspace.png" alt="" width="587" height="272" srcset="/wp-content/uploads/2016/12/tutorial_1_cpp_workspace.png 587w, /wp-content/uploads/2016/12/tutorial_1_cpp_workspace-300x139.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<ul>
<li><strong>工作区位置：</strong>保存工作区文件的目录，在该目录下会保存出*.workspace.xml的文件，该文件即是编辑器打开的工作区文件（或者称之为项目文件）。</li>
<li><strong>行为树源位置：</strong>对既有服务器，又有客户端的项目开发，可能需要共用行为树，这时候只要为服务器和客户端分别创建工作区，然后为它们设置相同的“行为树源位置”即可。这样，只需要编辑同一份行为树，就可以让服务器和客户端的AI逻辑保持一致。此外，源位置中还自动生成behaviac_meta文件夹，里面保存了跟工作区同名但后缀名为*.meta.xml的类型信息文件。</li>
<li><strong>行为树导出位置：</strong>在该目录下，导出编辑好的行为树，并且需要在程序端设置的加载位置，以便程序运行起来后，加载所需的行为树。</li>
<li><strong>代码生成位置：</strong>用于存放后面将要描述的类型信息浏览器中编辑好的类型代码文件，还包含了一些“胶水”代码文件，都需要整合到运行时（游戏端）一起编译构建。</li>
<li><strong>程序端开发语言：</strong>可选cpp（即C++）和cs（即C#）两种，表示程序端的代码语言。结合上面所说的情况，可以支持服务器和客户端采用不同的语言编写代码，但共用同一份行为树数据。</li>
</ul>
<pre>“胶水”代码：是指编辑器自动生成的代码文件，用于注册类型信息，并用于程序端执行时通过名字或ID调用类的成员属性或方法。</pre>
<p>点击确认后，就可以创建自己的工作区。创建完工作区之后，后续如果需要修改工作区中的参数，可以通过菜单项“文件”-&gt;“编辑工作区”，重新打开上图所示的窗口来修改相关的参数。</p>
<p>另外，还可以直接打开为本教程建好的工作区。点击菜单项“文件”-&gt;“打开工作区”，找到安装或源码包目录中的<a href="https://github.com/Tencent/behaviac/tree/master/tutorials/tutorial_1/workspace">tutorials/tutorial_1/workspace</a>文件夹，打开tutorial_1_cpp.workspace.xml文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1570" src="/wp-content/uploads/2016/12/tutorial_1_workspace.png" alt="" width="268" height="207" /></p>
<h3><span class="ez-toc-section" id="i-4">编辑类型信息</span></h3>
<p>为了让行为树可以描述某个Agent类型的行为，首先需要创建自己的Agent子类。</p>
<h4><span class="ez-toc-section" id="i-5">视频</span></h4>
<p align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_1_1.mp4" controls="controls" width="640" height="480"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p>通过菜单项“视图”-&gt;“类型信息”（或快捷键Ctrl+M），打开类型信息浏览器，可以看到当前类型列表中只有一个默认生成的behaviac::Agent基类，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1338" src="/wp-content/uploads/2016/12/empty_types.png" alt="empty_types" width="612" height="735" srcset="/wp-content/uploads/2016/12/empty_types.png 612w, /wp-content/uploads/2016/12/empty_types-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>点击右上角的“新增”按钮，弹出“新增类型”窗口，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1339" src="/wp-content/uploads/2016/12/first_agent.png" alt="first_agent" width="370" height="270" srcset="/wp-content/uploads/2016/12/first_agent.png 370w, /wp-content/uploads/2016/12/first_agent-300x219.png 300w" sizes="(max-width: 370px) 100vw, 370px" /></p>
<ul>
<li>将“类型”选择为“Agent”</li>
<li>将“名称”设置为“FirstAgent”</li>
<li>右上方的“生成代码?”默认是勾选上的，表示编辑器要自动生成该类型的代码文件，否则该类型代码需要手工编写</li>
<li>“生成位置”是生成该类型文件所在的文件夹，默认不用设置，表示默认生成在工作区中配置的“代码生成位置”里面</li>
</ul>
<p>点击“确定”按钮后，可以看到类型列表中有了“FirstAgent”这个类，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1340" src="/wp-content/uploads/2016/12/first_agent_methods.png" alt="first_agent_methods" width="612" height="735" srcset="/wp-content/uploads/2016/12/first_agent_methods.png 612w, /wp-content/uploads/2016/12/first_agent_methods-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>选中该“FirstAgent”类，并设置中部的 “成员类型”为“Method”，可以看到目前该类有六个来自behaviac::Agent基类的成员方法，方法名前面的“~”表示该方法是从基类继承过来的，如上图所示。</p>
<p>点击右侧的“新增”按钮，弹出“新增方法”窗口，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1341" src="/wp-content/uploads/2016/12/create_SayHello.png" alt="create_sayhello" width="562" height="343" srcset="/wp-content/uploads/2016/12/create_SayHello.png 562w, /wp-content/uploads/2016/12/create_SayHello-300x183.png 300w" sizes="(max-width: 562px) 100vw, 562px" /></p>
<p>将新方法的“名字”设为“SayHello”，其他参数暂不用设置。</p>
<p>直接点击“确定”按钮，回到类型信息浏览器，可以看到“FirstAgent”类有了第一个自己添加的成员方法“SayHello”，其他几个带“~”的方法表示是从基类继承过来的成员方法，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1342" src="/wp-content/uploads/2016/12/first_method-1.png" alt="first_method" width="612" height="735" srcset="/wp-content/uploads/2016/12/first_method-1.png 612w, /wp-content/uploads/2016/12/first_method-1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>现在，我们有了第一个Agent子类的“FirstAgent”，以及它的成员方法“SayHello”。</p>
<p>点击右下方的“应用”按钮，自动生成类型和其他相关的“胶水”代码文件等。</p>
<p>点击左下方的“打开代码生成位置”按钮，可以查看生成的代码文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1318" src="/wp-content/uploads/2016/12/generated_types.png" alt="generated_types" width="234" height="168" /></p>
<p>其中，behaviac_types.h需要包含到自己的代码中，以便使用自动生成的类型和“胶水”代码，如下代码所示：</p>
<pre>#include "behaviac_generated/types/behaviac_types.h"</pre>
<p>“internal”文件夹中包含了前面提及的类型和“胶水”代码，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1343" src="/wp-content/uploads/2016/12/generated_internal-1.png" alt="generated_internal" width="269" height="267" srcset="/wp-content/uploads/2016/12/generated_internal-1.png 269w, /wp-content/uploads/2016/12/generated_internal-1-150x150.png 150w" sizes="(max-width: 269px) 100vw, 269px" /></p>
<p>其中，behaviac_agent_member_visitor.h文件生成了用于访问类的私有属性和方法的“胶水”代码，behaviac_agent_meta.h/cpp文件生成了用于注册类及其属性、方法、实例等信息的“胶水”代码，这些“胶水”代码主要是为了程序端可以通过名字自动取用到类及其成员属性、方法及其实例等。</p>
<p>这些生成的代码需要添加到自己的项目中一起编译构建，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1344" src="/wp-content/uploads/2016/12/include_project-1.png" alt="include_project" width="286" height="247" /></p>
<h3><span class="ez-toc-section" id="i-6">创建行为树</span></h3>
<p>有了上面创建的Agent子类“FirstAgent”后，就可以开始创建和编辑行为树了。</p>
<h4><span class="ez-toc-section" id="i-7">视频</span></h4>
<p align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_1_2.mp4" controls="controls" width="640" height="480"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p>如果对编辑器的按键操作不熟悉，请通过菜单项“帮助”-&gt;“起始页”，查看按键说明，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1346" src="/wp-content/uploads/2016/12/controls.png" alt="controls" width="646" height="612" srcset="/wp-content/uploads/2016/12/controls.png 646w, /wp-content/uploads/2016/12/controls-300x284.png 300w" sizes="(max-width: 646px) 100vw, 646px" /></p>
<p>点击工具栏中的“新建行为树”按钮，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1347" src="/wp-content/uploads/2016/12/new_bt-1.png" alt="new_bt" width="285" height="116" /></p>
<p>新建行为树后，将该行为树名字改为“FirstBT”，现在有了第一棵行为树，该树只有一个根节点，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1348" src="/wp-content/uploads/2016/12/first_bt-1.png" alt="first_bt" width="599" height="290" srcset="/wp-content/uploads/2016/12/first_bt-1.png 599w, /wp-content/uploads/2016/12/first_bt-1-300x145.png 300w" sizes="(max-width: 599px) 100vw, 599px" /></p>
<p>鼠标左键单击选中该根节点，为该节点的“Agent类型”设置为前面创建的“FirstAgent”，表示这棵行为树用来描述FirstAgent类的行为，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1198" src="/wp-content/uploads/2016/12/agent_type.png" sizes="(max-width: 475px) 100vw, 475px" srcset="/wp-content/uploads/2016/12/agent_type.png 475w, /wp-content/uploads/2016/12/agent_type-300x85.png 300w" alt="agent_type" width="475" height="135" /></p>
<p>设置完后，可以发现根节点已经具有类型“FirstAgent”，如下图所示：</p>
<div><img class="aligncenter size-full wp-image-1349" src="/wp-content/uploads/2016/12/root_node.png" alt="root_node" width="602" height="297" srcset="/wp-content/uploads/2016/12/root_node.png 602w, /wp-content/uploads/2016/12/root_node-300x148.png 300w" sizes="(max-width: 602px) 100vw, 602px" /></div>
<div></div>
<p>在左侧的节点列表中（如下图所示），用鼠标左键选中“动作”节点（或其他需要的节点）后，按住鼠标左键并拖拽该节点到右侧的主视口中，并将动作节点落在根节点右侧的黑色三角箭头处。</p>
<p><img class="aligncenter size-full wp-image-1199" src="/wp-content/uploads/2016/12/node_tree.png" sizes="(max-width: 170px) 100vw, 170px" srcset="/wp-content/uploads/2016/12/node_tree.png 170w, /wp-content/uploads/2016/12/node_tree-134x300.png 134w" alt="node_tree" width="170" height="381" /></p>
<p>拖拽完毕，可以看到行为树有了叶子节点“动作”，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1350" src="/wp-content/uploads/2016/12/action_node.png" alt="action_node" width="874" height="294" srcset="/wp-content/uploads/2016/12/action_node.png 874w, /wp-content/uploads/2016/12/action_node-300x101.png 300w, /wp-content/uploads/2016/12/action_node-768x258.png 768w" sizes="(max-width: 874px) 100vw, 874px" /></p>
<p>选中该动作节点，在右侧“动作的属性”窗口中，为其选择成员方法“SayHello”，并将另一参数“决定状态的选项”设置为“Success”，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1322" src="/wp-content/uploads/2016/12/action_properties.png" alt="action_properties" width="476" height="102" srcset="/wp-content/uploads/2016/12/action_properties.png 476w, /wp-content/uploads/2016/12/action_properties-300x64.png 300w" sizes="(max-width: 476px) 100vw, 476px" /></p>
<p>如果想了解动作节点的更多细节，请参考文档《<a href="/language/zh/action/">动作节点</a>》。或者选中某个节点后，按F1键或右键菜单直接打开该节点的文档。</p>
<p>至此，我们得到了一棵最简单但是完整的行为树，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1351" src="/wp-content/uploads/2016/12/first_bt_tree-1.png" alt="first_bt_tree" width="876" height="293" srcset="/wp-content/uploads/2016/12/first_bt_tree-1.png 876w, /wp-content/uploads/2016/12/first_bt_tree-1-300x100.png 300w, /wp-content/uploads/2016/12/first_bt_tree-1-768x257.png 768w" sizes="(max-width: 876px) 100vw, 876px" /></p>
<h3><span class="ez-toc-section" id="i-8">导出行为树</span></h3>
<p>编辑完行为树后，需要导出全部行为树，以便程序端加载使用。</p>
<h4><span class="ez-toc-section" id="i-9">视频</span></h4>
<p align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_1_3.mp4" controls="controls" width="640" height="480"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p>点击工具栏中的“导出全部”按钮，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1359" src="/wp-content/uploads/2016/12/export_all-1.png" alt="export_all" width="285" height="113" /></p>
<p>弹出“导出”窗口，在导出格式中暂只用勾选“Xml”，点击右下方的“导出”按钮，如下图所示： <img class="aligncenter size-full wp-image-1323" src="/wp-content/uploads/2016/12/export_bt.png" alt="export_bt" width="395" height="595" srcset="/wp-content/uploads/2016/12/export_bt.png 395w, /wp-content/uploads/2016/12/export_bt-199x300.png 199w" sizes="(max-width: 395px) 100vw, 395px" /></p>
<p>导出后，打开工作区中指定的导出目录，可以看到成功导出了FirstBT.xml文件和meta文件夹中的tutorial_1_cpp.meta.xml文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1571" src="/wp-content/uploads/2016/12/tutorial_1_cpp_exported.png" alt="" width="284" height="165" /></p>
<p>导出的FirstBT.xml文件就是交给程序端加载使用的行为树，tutorial_1_cpp.meta.xml文件是交给程序端加载使用的含有类型和自定义成员属性信息的文件。</p>
<h2><span class="ez-toc-section" id="i-10">运行时的使用</span></h2>
<h3><span class="ez-toc-section" id="i-11">编写并运行程序</span></h3>
<p>需要整合behaviac运行时库到自己的项目中来一起编译构建和运行行为树。<strong>如何编译构建behaviac运行时库，请参考文档《<a href="/language/zh/how_to_build/">如何编译构建</a>》。</strong></p>
<h4><span class="ez-toc-section" id="C">C++版</span></h4>
<p align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_2.mp4" controls="controls" width="640" height="480"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p style="text-align: left;" align="center">对于自己的C++项目，需要包含behaviac库的inc目录（该inc目录位于源码压缩包的最顶级）。例如，对于Visual Studio项目，inc目录配置如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1387" src="/wp-content/uploads/2016/12/include_headers.png" alt="include_headers" width="718" height="582" srcset="/wp-content/uploads/2016/12/include_headers.png 718w, /wp-content/uploads/2016/12/include_headers-300x243.png 300w" sizes="(max-width: 718px) 100vw, 718px" /></p>
<p>同时还需要包含编译behaviac生成的lib文件。例如，对于Visual Studio项目，behaviac lib文件配置如下图所示</p>
<p><img class="aligncenter size-full wp-image-1388" src="/wp-content/uploads/2016/12/include_lib-1.png" alt="include_lib" width="722" height="589" srcset="/wp-content/uploads/2016/12/include_lib-1.png 722w, /wp-content/uploads/2016/12/include_lib-1-300x245.png 300w" sizes="(max-width: 722px) 100vw, 722px" /></p>
<p>将编辑器生成的Agent子类的类型和相关的“胶水”代码都整合到自己的项目中，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1572" src="/wp-content/uploads/2016/12/tutorial_1_cpp_project.png" alt="" width="372" height="324" srcset="/wp-content/uploads/2016/12/tutorial_1_cpp_project.png 372w, /wp-content/uploads/2016/12/tutorial_1_cpp_project-300x261.png 300w" sizes="(max-width: 372px) 100vw, 372px" /></p>
<p>在tutorial_1.cpp文件中，通过使用behaviac组件提供的API来体现行为树是如何加载和执行起来的。</p>
<p><strong>首先，在InitBehaviac()方法中初始化behaviac的加载目录和文件格式等，如下代码所示：</strong></p>
<pre>bool InitBehavic()
{
    LOGI("InitBehavic\n");

    behaviac::Workspace::GetInstance()-&gt;SetFilePath("../tutorials/tutorial_1/cpp/exported");

    behaviac::Workspace::GetInstance()-&gt;SetFileFormat(behaviac::Workspace::EFF_xml);

    return true;
}</pre>
<p>上面的几个接口说明如下：</p>
<ul>
<li>Workspace::SetFilePath()用于设置加载编辑器导出的行为树所在的目录。</li>
<li>Workspace::SetFileFormat()用于设置加载的行为树格式，这里用的是xml格式。</li>
</ul>
<p><strong>接着，创建Agent子类“FirstAgent”的实例，并加载指定的行为树，这里的行为树名字为“FirstBT”，如下代码所示：</strong></p>
<pre>bool InitPlayer()
{
    LOGI("InitPlayer\n");

    g_FirstAgent = behaviac::Agent::Create&lt;FirstAgent&gt;();

    bool bRet = g_FirstAgent-&gt;btload("FirstBT");

    g_FirstAgent-&gt;btsetcurrent("FirstBT");

    return bRet;
}</pre>
<p>上面的几个接口说明如下：</p>
<ul>
<li>Agent::Create()用于创建Agent子类的实例。</li>
<li>Agent::btload()用于加载行为树，入口参数是行为树的名字，不要加后缀。</li>
<li>Agent::btsetcurrent()用于指定当前准备执行的行为树。</li>
</ul>
<p><strong>其次，开始执行行为树，如下代码所示：</strong></p>
<pre>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-&gt;btexec();
    }
}</pre>
<p>Agent::btexec()用于执行一次前面通过Agent::btsetcurrent()指定的行为树。</p>
<p>另外，如果不通过Agent::btexec()来单独执行行为树，也可以调用Workspace::Update()的方式来统一执行所有Agent实例的行为树，详见文章《<a href="/tutorial13_updateloop/">运行时端的执行流程</a>》。</p>
<p><strong>然后，对创建的Agent实例进行销毁释放，并清理整个工作区，如下代码所示：</strong></p>
<pre>void CleanupPlayer()
{
    LOGI("CleanupPlayer\n");

    behaviac::Agent::Destroy(g_FirstAgent);
}

void CleanupBehaviac()
{
    LOGI("CleanupBehaviac\n");

    behaviac::Workspace::GetInstance()-&gt;Cleanup();
}</pre>
<p><strong>最后，打开FirstAgent.cpp文件，并修改FirstAgent::SayHello()方法如下：</strong></p>
<pre>///&lt;&lt;&lt; THE METHOD HEAD
void FirstAgent::SayHello()
{
    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE
    printf("\nHello Behaviac!\n\n");
    ///&lt;&lt;&lt; END WRITING YOUR CODE
}</pre>
<p>注意：自己的代码需要添加在“///&lt;&lt;&lt; BEGIN WRITING YOUR CODE”和“///&lt;&lt;&lt; END WRITING YOUR CODE”之间，以便编辑器下次生成代码的时候，可以自动合并手工添加的内容和生成的内容。</p>
<p>编译并运行整个程序，执行结果如下：</p>
<p><img class="aligncenter size-full wp-image-1326" src="/wp-content/uploads/2016/12/exec_result.png" alt="exec_result" width="128" height="182" /></p>
<p>可以看到，程序结果输出了“Hello Behaviac!”，也就是成功执行了我们创建的第一棵最简单的行为树，并成功执行了动作节点配置的成员方法“SayHello”。</p>
<p>下载源码包后，打开projects目录中的工程文件behaviac.sln（Windows平台）或make文件（Linux平台），编译并执行tutorial_1项目，就可以看到上图的结果。</p>
<h4><span class="ez-toc-section" id="C-2">纯C#版</span></h4>
<p align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_3.mp4" controls="controls" width="640" height="480"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p style="text-align: left;" align="center">本教程纯C#版的工作区文件是安装包目录下的tutorials/tutorial_1/workspace/tutorial_1_cs.workspace.xml，相关参数配置如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1573" src="/wp-content/uploads/2016/12/tutorial_1_cs_workspace.png" alt="" width="587" height="272" srcset="/wp-content/uploads/2016/12/tutorial_1_cs_workspace.png 587w, /wp-content/uploads/2016/12/tutorial_1_cs_workspace-300x139.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<p>对于自己的C#项目，需要包含behaviac库的所有运行时源码（在源码包的<a href="https://github.com/Tencent/behaviac/tree/master/integration/unity/Assets/Scripts/behaviac/runtime">integration\unity\Assets\Scripts\behaviac\runtime</a>文件夹中）整合进来，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1574" src="/wp-content/uploads/2016/12/tutorial_1_cs_project.png" alt="" width="199" height="288" /></p>
<p>将编辑器生成的Agent子类的类型和相关的“胶水”代码都整合到自己的项目中，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1575" src="/wp-content/uploads/2016/12/tutorial_1_cs2_project.png" alt="" width="219" height="345" srcset="/wp-content/uploads/2016/12/tutorial_1_cs2_project.png 219w, /wp-content/uploads/2016/12/tutorial_1_cs2_project-190x300.png 190w" sizes="(max-width: 219px) 100vw, 219px" /></p>
<p>为项目添加条件编译宏BEHAVIAC_NOT_USE_UNITY，表示用的是纯C#模式，没有使用Unity相关的API，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1446" src="/wp-content/uploads/2016/12/cs_marco.png" alt="cs_marco" width="678" height="167" srcset="/wp-content/uploads/2016/12/cs_marco.png 678w, /wp-content/uploads/2016/12/cs_marco-300x74.png 300w" sizes="(max-width: 678px) 100vw, 678px" /></p>
<p>在tutorial_1.cs文件中，通过使用behaviac组件提供的API来体现行为树是如何加载和执行起来的。</p>
<p><strong>首先，在InitBehaviac()方法中初始化behaviac的加载目录和文件格式等，如下代码所示：</strong></p>
<pre>static bool InitBehavic()
{
    Console.WriteLine("InitBehavic");

    behaviac.Workspace.Instance.FilePath = "../../exported";
    behaviac.Workspace.Instance.FileFormat = behaviac.Workspace.EFileFormat.EFF_xml;

    return true;
}</pre>
<p>上面的几个接口说明如下：</p>
<ul>
<li>Workspace.FilePath用于设置加载编辑器导出的行为树所在的目录。</li>
<li>Workspace.FileFormat用于设置加载的行为树格式，这里用的是xml格式。</li>
</ul>
<p><strong>接着，创建Agent子类“FirstAgent”的实例，并加载指定的行为树，这里的行为树名字为“FirstBT”，如下代码所示：</strong></p>
<pre>static bool InitPlayer()
{
    Console.WriteLine("InitPlayer");

    g_FirstAgent = new FirstAgent();

    bool bRet = g_FirstAgent.btload("FirstBT");
    Debug.Assert(bRet);

    g_FirstAgent.btsetcurrent("FirstBT");

    return bRet;
}</pre>
<p>上面的几个接口说明如下：</p>
<ul>
<li>Agent.btload()用于加载行为树，入口参数是行为树的名字，不要加后缀。</li>
<li>Agent.btsetcurrent()用于指定当前准备执行的行为树。</li>
</ul>
<p><strong>其次，开始执行行为树，如下代码所示：</strong></p>
<pre>static void UpdateLoop()
{
    Console.WriteLine("UpdateLoop");

    int frames = 0;
    behaviac.EBTStatus status = behaviac.EBTStatus.BT_RUNNING;

    while (status == behaviac.EBTStatus.BT_RUNNING)
    {
        Console.WriteLine("frame {0}", ++frames);

        status = g_FirstAgent.btexec();
    }
}</pre>
<p>Agent.btexec()用于执行一次前面通过Agent.btsetcurrent()指定的行为树。</p>
<p><strong>然后，对创建的Agent实例进行销毁释放，并清理整个工作区，如下代码所示：</strong></p>
<pre>static void CleanupPlayer()
{
    Console.WriteLine("CleanupPlayer");

    g_FirstAgent = null;
}

static void CleanupBehaviac()
{
    Console.WriteLine("CleanupBehaviac");

    behaviac.Workspace.Instance.Cleanup();
}</pre>
<p><strong>最后，打开FirstAgent.cs文件，并修改SayHello()方法如下：</strong></p>
<pre>///&lt;&lt;&lt; THE METHOD HEAD
public void SayHello()
{
    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE
    Console.WriteLine();
    Console.WriteLine("Hello Behaviac!");
    Console.WriteLine();
    ///&lt;&lt;&lt; END WRITING YOUR CODE
}</pre>
<p>注意：自己的代码需要添加在“///&lt;&lt;&lt; BEGIN WRITING YOUR CODE”和“///&lt;&lt;&lt; END WRITING YOUR CODE”之间，以便编辑器下次生成代码的时候，可以自动合并手工添加的内容和生成的内容。</p>
<p>编译并运行整个程序，执行结果如下：</p>
<p><img class="aligncenter size-full wp-image-1326" src="/wp-content/uploads/2016/12/exec_result.png" alt="exec_result" width="128" height="182" /></p>
<p>可以看到，程序结果输出了“Hello Behaviac!”，也就是成功执行了我们创建的第一棵最简单的行为树，并成功执行了动作节点配置的成员方法“SayHello”。</p>
<p>下载源码包后，打开<a href="https://github.com/Tencent/behaviac/tree/master/tutorials/CsTutorials">tutorials/CsTutorials</a>目录中的工程文件<a id="12bd5ecb3f1c6dd4105af1cf9b665687-972df3316d1408803517f097a5db6f87b6f44981" class="js-navigation-open" title="CsTutorials.sln" href="https://github.com/Tencent/behaviac/blob/master/tutorials/CsTutorials/CsTutorials.sln">CsTutorials.sln</a>，编译并执行tutorial_1项目，就可以看到上图的结果。</p>
<h4><span class="ez-toc-section" id="Unity_C">Unity C#版</span></h4>
<p align="center"><video src="http://dlied5.qq.com/behaviac/tutorial_0_4.mp4" controls="controls" width="640" height="480"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p style="text-align: left;" align="center">打开Unity编辑器创建一个空的Unity项目，保存该项目，或者直接打开安装目录下的tutorials/tutorial_1/unity目录中的项目。</p>
<p>通过behaviac编辑器创建一个工作区（或者直接打开安装包目录下的Unity工作区文件<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_1/workspace/tutorial_1_unity.workspace.xml">tutorials/tutorial_1/workspace/tutorial_1_unity.workspace.xml</a>），相关参数配置如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1576" src="/wp-content/uploads/2016/12/tutorial_1_unity_workspace.png" alt="" width="587" height="272" srcset="/wp-content/uploads/2016/12/tutorial_1_unity_workspace.png 587w, /wp-content/uploads/2016/12/tutorial_1_unity_workspace-300x139.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<p>添加FirstAgent类及其成员方法SayHello()、创建和导出行为树FirstBT等流程跟上文相同。</p>
<p>导出整个工作区后，可以看到在目录<a href="https://github.com/Tencent/behaviac/tree/master/tutorials/tutorial_1/unity/Assets/Scripts/behaviac/behaviac_generated/types">tutorials\tutorial_1\unity\Assets\Scripts\behaviac\behaviac_generated\types</a>有了自动生成的源码文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1433" src="/wp-content/uploads/2016/12/unity_export.png" alt="unity_export" width="273" height="201" /></p>
<p>在Unity编辑器中导入安装包目录下的behaviac运行时包integration/behaviac***.unitypackage。</p>
<p>打开整个项目的源码工程，可以看到有了behaviac的运行时库runtime和编辑器生成的源码behaviac_generated，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1434" src="/wp-content/uploads/2016/12/unity_code.png" alt="unity_code" width="277" height="384" srcset="/wp-content/uploads/2016/12/unity_code.png 277w, /wp-content/uploads/2016/12/unity_code-216x300.png 216w" sizes="(max-width: 277px) 100vw, 277px" /></p>
<p>打开FirstAgent.cs文件，添加代码如下：</p>
<p><strong>首先，在InitBehaviac()方法中初始化behaviac的加载目录和文件格式等，如下代码所示：</strong></p>
<pre>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");

    <strong>behaviac.Workspace.Instance.FilePath</strong> = ExportedFilePath;
    <strong>behaviac.Workspace.Instance.FileFormat</strong> = behaviac.Workspace.EFileFormat.EFF_xml;

    return true;
}</pre>
<p><strong>接着，加载指定的行为树，这里的行为树名字为“FirstBT”，如下代码所示：</strong></p>
<pre>private bool InitPlayer()
{
    behaviac.Debug.LogWarning("InitPlayer");

    bool bRet = this.btload("FirstBT");
    if (bRet)
    {
        this.btsetcurrent("FirstBT");
    }

    return bRet;
}</pre>
<p>在Awake()方法中调用InitBehavic和InitPlayer方法，如下代码所示：</p>
<pre>void Awake()
{
    InitBehavic();

    InitPlayer();
}</pre>
<p><strong>其次，在Update()方法中执行行为树，如下代码所示：</strong></p>
<pre>behaviac.EBTStatus _status = behaviac.EBTStatus.BT_RUNNING;

void Update()
{
    if (_status == behaviac.EBTStatus.BT_RUNNING)
    {
        behaviac.Debug.LogWarning("Update");

        _status = this.btexec();
     }
}</pre>
<p><strong>然后，修改SayHello()方法如下：</strong></p>
<pre>public void SayHello()
{
    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE SayHello
    behaviac.Debug.LogWarning("Hello Behaviac!");
    ///&lt;&lt;&lt; END WRITING YOUR CODE
}</pre>
<p>注意：自己的代码需要添加在“///&lt;&lt;&lt; BEGIN WRITING YOUR CODE”和“///&lt;&lt;&lt; END WRITING YOUR CODE”之间，以便编辑器下次生成代码的时候，可以自动合并手工添加的内容和生成的内容。</p>
<p>最后，在Unity编辑器中添加一个GameObject，并且为其添加脚本组件FirstAgent，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1435" src="/wp-content/uploads/2016/12/unity_component.png" alt="unity_component" width="390" height="151" srcset="/wp-content/uploads/2016/12/unity_component.png 390w, /wp-content/uploads/2016/12/unity_component-300x116.png 300w" sizes="(max-width: 390px) 100vw, 390px" /></p>
<p>在Unity编辑器中运行这个简单的程序，执行结果如下：</p>
<p><img class="aligncenter size-full wp-image-1436" src="/wp-content/uploads/2016/12/unity_output.png" alt="unity_output" width="262" height="176" /></p>
<p>下载源码包后，通过Unity编辑器打开并运行<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_1/unity">tutorials/tutorial_1/unity</a>目录中的项目，就可以看到上图的结果。</p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_1">tutorials/tutorial_1</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_1_hello_behaviac/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>教程1.1：编辑器生成类型代码的工作流程</title>
		<link>/tutorial_1_1_generate_codes/</link>
					<comments>/tutorial_1_1_generate_codes/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Tue, 07 Mar 2017 04:04:05 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1733</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 如《教程1：Hello Behaviac》所述，程序端的类型代码可以通过编辑器自<a class="moretag" href="/tutorial_1_1_generate_codes/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>如《<a href="/tutorial_1_hello_behaviac/">教程1：Hello Behaviac</a>》所述，程序端的类型代码可以通过编辑器自动生成基本原型，然后在生成的代码模板上继续添加自己的逻辑代码。</p>
<p>本教程将详细介绍相关的具体操作步骤，包括：从创建Agent类型到生成其代码文件，并利用该Agent类型创建行为树，最后执行该行为树的流程。</p>
<h2><span class="ez-toc-section" id="1_Agent">1. 新建Agent类型</span></h2>
<p>通过编辑器的菜单项“视图”-&gt;“类型信息”（或快捷键Ctrl+M），打开类型信息浏览器，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1338" src="/wp-content/uploads/2016/12/empty_types.png" sizes="(max-width: 612px) 100vw, 612px" srcset="/wp-content/uploads/2016/12/empty_types.png 612w, /wp-content/uploads/2016/12/empty_types-250x300.png 250w" alt="empty_types" width="612" height="735" /></p>
<p>点击右上角的“新增”按钮，弹出“新增类型”窗口，添加FirstAgent类，勾选“生成代码”选项，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1774" src="/wp-content/uploads/2017/03/ZMJHZIMHCVT2V7O_@Q.png" alt="" width="368" height="268" srcset="/wp-content/uploads/2017/03/ZMJHZIMHCVT2V7O_@Q.png 368w, /wp-content/uploads/2017/03/ZMJHZIMHCVT2V7O_@Q-300x218.png 300w" sizes="(max-width: 368px) 100vw, 368px" /></p>
<p>更详细的类型信息编辑过程以及相关操作面板的参数说明，请参考文章《<a href="/edit_types/">编辑类型信息</a>》。</p>
<h2><span class="ez-toc-section" id="2">2. 新增成员属性</span></h2>
<p>为FirstAgent类添加int类型的成员属性p1，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1677" src="/wp-content/uploads/2017/03/second_agent_p1.png" alt="" width="489" height="293" srcset="/wp-content/uploads/2017/03/second_agent_p1.png 489w, /wp-content/uploads/2017/03/second_agent_p1-300x180.png 300w" sizes="(max-width: 489px) 100vw, 489px" /></p>
<h2><span class="ez-toc-section" id="3">3. 新增成员方法</span></h2>
<p>再为FirstAgent类添加成员方法m1，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1679" src="/wp-content/uploads/2017/03/second_agent_m1-1.png" alt="" width="562" height="343" srcset="/wp-content/uploads/2017/03/second_agent_m1-1.png 562w, /wp-content/uploads/2017/03/second_agent_m1-1-300x183.png 300w" sizes="(max-width: 562px) 100vw, 562px" /></p>
<p>添加完FirstAgent类型及其成员属性和方法之后，可以在类型信息浏览器中看到如下所示：</p>
<p><img class="aligncenter size-full wp-image-1729" src="/wp-content/uploads/2017/03/tutorial_1_1_m1.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/03/tutorial_1_1_m1.png 612w, /wp-content/uploads/2017/03/tutorial_1_1_m1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2><span class="ez-toc-section" id="4">4. 修改成员</span></h2>
<p>如果修改了成员属性和方法，例如改名、加参数等操作后，只需点击右下方的“应用”按钮即可。</p>
<p>例如，将成员属性p1改名为p2，如下图所示：</p>
<p id="vBPmkxS"><img class="size-full wp-image-1742 aligncenter" src="/wp-content/uploads/2017/03/img_58be330b3e5b1.png" alt="" srcset="/wp-content/uploads/2017/03/img_58be330b3e5b1.png 612w, /wp-content/uploads/2017/03/img_58be330b3e5b1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2><span class="ez-toc-section" id="5">5. 生成代码</span></h2>
<p>点击右下方的“应用”按钮，在工作区配置的“代码生成位置”生成了类型及其相关的“胶水”代码文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1734" src="/wp-content/uploads/2017/03/generated_types.png" alt="" width="234" height="168" /></p>
<p>在上图中的internal文件夹中生成了Agent类型及其“胶水”代码，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1735" src="/wp-content/uploads/2017/03/generated_internal2.png" alt="" width="256" height="265" /></p>
<p>需要将types文件夹中的所有代码文件都加到自己的项目中一起编译构建，并只需在程序端代码中包含头文件types/behaviac_types.h即可，其他“胶水”代码头文件不用包含，如下代码所示：</p>
<pre>#include "behaviac_generated/types/behaviac_types.h"</pre>
<h2><span class="ez-toc-section" id="6">6. 添加逻辑代码</span></h2>
<p>打开上面生成的FirstAgent.cpp文件，为FirstAgent::m1方法添加自己的逻辑代码。注意所有自己添加的代码都需要添加在注释“///&lt;&lt;&lt; BEGIN WRITING YOUR CODE”和“///&lt;&lt;&lt; END WRITING YOUR CODE”之间，如下代码所示：</p>
<pre>#include "FirstAgent.h"

///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FILE_INIT

///&lt;&lt;&lt; END WRITING YOUR CODE

FirstAgent::FirstAgent()
{
    p1 = 0;
///&lt;&lt;&lt; BEGIN WRITING YOUR CODE CONSTRUCTOR

///&lt;&lt;&lt; END WRITING YOUR CODE
}

FirstAgent::~FirstAgent()
{
///&lt;&lt;&lt; BEGIN WRITING YOUR CODE DESTRUCTOR

///&lt;&lt;&lt; END WRITING YOUR CODE
}

void FirstAgent::m1(behaviac::string&amp; value)
{
///&lt;&lt;&lt; BEGIN WRITING YOUR CODE m1
    printf("\n%s\n\n", value.c_str());
///&lt;&lt;&lt; END WRITING YOUR CODE
}

///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FILE_UNINIT

///&lt;&lt;&lt; END WRITING YOUR CODE</pre>
<p>如果在类型信息浏览器中将成员方法m1改名为m2，点击右下方的“应用”按钮，重新生成代码，上面代码中的m1会自动变为m2，在BEGIN和END之间的手写代码不会改变，会自动保留。</p>
<h2><span class="ez-toc-section" id="7">7. 添加行为树</span></h2>
<p>利用新加的FirstAgent类及其成员属性和方法，添加行为树“FirstBT”，如下图所示：</p>
<p id="nDoLHXC"><img class="size-full wp-image-1737 aligncenter" src="/wp-content/uploads/2017/03/img_58be2d939f783.png" alt="" srcset="/wp-content/uploads/2017/03/img_58be2d939f783.png 849w, /wp-content/uploads/2017/03/img_58be2d939f783-300x102.png 300w, /wp-content/uploads/2017/03/img_58be2d939f783-768x261.png 768w" sizes="(max-width: 849px) 100vw, 849px" /></p>
<h2><span class="ez-toc-section" id="8">8. 执行行为树</span></h2>
<p>加载并执行该行为树，可以看到输出结果如下图所示：</p>
<p id="iyDmJKn"><img class="size-full wp-image-1738 aligncenter" src="/wp-content/uploads/2017/03/img_58be2ff985e5c.png" alt="" /></p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_1_1">tutorials/tutorial_1_1</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_1_1_generate_codes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程1.2：手工编写类型代码的工作流程</title>
		<link>/tutorial_1_2_write_codes/</link>
					<comments>/tutorial_1_2_write_codes/#comments</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Tue, 07 Mar 2017 09:02:50 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1745</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 在《教程1.1：编辑器生成类型代码的工作流程》中，介绍了通过编辑器自动生成类型代<a class="moretag" href="/tutorial_1_2_write_codes/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>在《<a href="/language/zh/tutorial_1_1_generate_codes/">教程1.1：编辑器生成类型代码的工作流程</a>》中，介绍了通过编辑器自动生成类型代码的基本原型，然后在生成的代码模板上继续添加自己的逻辑代码。</p>
<p>而对于习惯手工编写代码，或已经有了大量手工编写的类型代码（如从老版本升级到3.6新版本），可以依然使用原来的代码，但需要在编辑器中创建对应的类型信息。</p>
<p>本教程详细介绍相关的具体步骤，包括：从创建Agent类型到手工编辑代码文件，并利用该Agent类型创建行为树，最后执行该行为树的结果。</p>
<h2><span class="ez-toc-section" id="1_Agent">1. 新建Agent类型</span></h2>
<p>首先需要在编辑器中创建跟程序端同名的Agent类型。</p>
<p>通过编辑器的菜单项“视图”-&gt;“类型信息”（或快捷键Ctrl+M），打开类型信息浏览器，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1338" src="/wp-content/uploads/2016/12/empty_types.png" sizes="(max-width: 612px) 100vw, 612px" srcset="/wp-content/uploads/2016/12/empty_types.png 612w, /wp-content/uploads/2016/12/empty_types-250x300.png 250w" alt="empty_types" width="612" height="735" /></p>
<p>点击右上角的“新增”按钮，弹出“新增类型”窗口，添加SecondAgent类，不要勾选“生成代码”选项，如下图所示：</p>
<p id="cXfcXis"><img class="aligncenter size-full wp-image-1776" src="/wp-content/uploads/2017/03/N_3QM45CYYZI2QB2R7.png" alt="" width="367" height="269" srcset="/wp-content/uploads/2017/03/N_3QM45CYYZI2QB2R7.png 367w, /wp-content/uploads/2017/03/N_3QM45CYYZI2QB2R7-300x220.png 300w" sizes="(max-width: 367px) 100vw, 367px" /></p>
<p>详细的类型信息编辑过程以及相关操作面板的参数说明，请参考文章《<a href="/edit_types/">编辑类型信息</a>》。</p>
<h2><span class="ez-toc-section" id="2">2. 新增成员属性</span></h2>
<p>为SecondAgent类添加int类型的成员属性p1，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1677" src="/wp-content/uploads/2017/03/second_agent_p1.png" alt="" width="489" height="293" srcset="/wp-content/uploads/2017/03/second_agent_p1.png 489w, /wp-content/uploads/2017/03/second_agent_p1-300x180.png 300w" sizes="(max-width: 489px) 100vw, 489px" /></p>
<h2><span class="ez-toc-section" id="3">3. 新增成员方法</span></h2>
<p>再为SecondAgent类添加成员方法m1，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1679" src="/wp-content/uploads/2017/03/second_agent_m1-1.png" alt="" width="562" height="343" srcset="/wp-content/uploads/2017/03/second_agent_m1-1.png 562w, /wp-content/uploads/2017/03/second_agent_m1-1-300x183.png 300w" sizes="(max-width: 562px) 100vw, 562px" /></p>
<p>添加完SecondAgent类型及其成员属性和方法之后，可以在类型信息浏览器中看到如下所示：</p>
<p id="SRVWxpY"><img class="size-full wp-image-1750 aligncenter" src="/wp-content/uploads/2017/03/img_58be6912ed3c2.png" alt="" srcset="/wp-content/uploads/2017/03/img_58be6912ed3c2.png 612w, /wp-content/uploads/2017/03/img_58be6912ed3c2-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2><span class="ez-toc-section" id="4">4. 修改成员</span></h2>
<p>如果修改了成员属性和方法，例如改名、加参数等操作后，只需点击右下方的“应用”按钮即可。</p>
<p>例如，将成员属性p1改名为p2，如下图所示：</p>
<p id="bXEXlzm"><img class="size-full wp-image-1751 aligncenter" src="/wp-content/uploads/2017/03/img_58be693c70aec.png" alt="" srcset="/wp-content/uploads/2017/03/img_58be693c70aec.png 612w, /wp-content/uploads/2017/03/img_58be693c70aec-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2><span class="ez-toc-section" id="5">5. 生成“胶水”代码</span></h2>
<p>点击右下方的“应用”按钮，在工作区配置的“代码生成位置”生成了“胶水”代码文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1734" src="/wp-content/uploads/2017/03/generated_types.png" alt="" width="234" height="168" /></p>
<p>在上图中的internal文件夹中生成了Agent类型的“胶水”代码，但并没有生成SecondAgent类型本身的代码文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1753" src="/wp-content/uploads/2017/03/AH3V7_YC95HUDH_R_0.png" alt="" width="260" height="229" /></p>
<p>需要将types文件夹中的所有代码文件都加到自己的项目中一起编译构建，并只需在程序端代码中包含头文件types/behaviac_types.h即可，其他“胶水”代码头文件不用包含，如下代码所示：</p>
<pre>#include "behaviac_generated/types/behaviac_types.h"</pre>
<h2><span class="ez-toc-section" id="6">6. 添加类型代码</span></h2>
<p>在代码项目中手工添加SecondAgent.h/.cpp文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1755" src="/wp-content/uploads/2017/03/4Y4SEE1S06MG0AWNV50.png" alt="" width="201" height="254" /></p>
<p>为了提高手工编写代码的效率并<strong>保持与编辑器中定义的一致性</strong>，请点击类型信息浏览器中的“预览原型代码”按钮，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1756" src="/wp-content/uploads/2017/03/CF_L3HI43674KSL6LFFEG.png" alt="" width="609" height="236" srcset="/wp-content/uploads/2017/03/CF_L3HI43674KSL6LFFEG.png 609w, /wp-content/uploads/2017/03/CF_L3HI43674KSL6LFFEG-300x116.png 300w" sizes="(max-width: 609px) 100vw, 609px" /></p>
<p>可以看到SecondAgent类的原型代码如下所示，复制粘贴需要的类型、成员属性或方法的申明代码到自己的SecondAgent.h头文件中：</p>
<pre>#ifndef _BEHAVIAC_SECONDAGENT_H_
#define _BEHAVIAC_SECONDAGENT_H_

#include "behaviac_headers.h"

class SecondAgent : public behaviac::Agent
{
public:
    SecondAgent();

    virtual ~SecondAgent();

    BEHAVIAC_DECLARE_AGENTTYPE(SecondAgent, behaviac::Agent)

private: int p1;

private: void m1(behaviac::string&amp; value);

};

#endif</pre>
<p>在SecondAgent.cpp中实现该类的各个方法如下所示：</p>
<pre>#include "SecondAgent.h"

SecondAgent::SecondAgent()
    : p1(0)
{
}

SecondAgent::~SecondAgent()
{
}

void SecondAgent::m1(behaviac::string&amp; value)
{
    printf("\n%s\n\n", value.c_str());
}</pre>
<p>在类型信息浏览器中点击右上方的”设置头文件“，添加刚才手工新建的SecondAgent类的头文件路径，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1784" src="/wp-content/uploads/2017/03/VNTEOT06BV8_AAV6NCKAH.png" alt="" width="519" height="267" srcset="/wp-content/uploads/2017/03/VNTEOT06BV8_AAV6NCKAH.png 519w, /wp-content/uploads/2017/03/VNTEOT06BV8_AAV6NCKAH-300x154.png 300w" sizes="(max-width: 519px) 100vw, 519px" /></p>
<p>这样在生成的types/internal/behaviac_headers.h文件中，就自动包含了上面添加的SecondAgent.h头文件，如下代码所示：</p>
<pre>#ifndef _BEHAVIAC_HEADERS_H_
#define _BEHAVIAC_HEADERS_H_

#include "behaviac/behaviac.h"

// YOU SHOULD SET THE HEADER FILES OF YOUR GAME WHEN EXPORTING CPP FILES ON THE BEHAVIAC EDITOR:
#include "../../../SecondAgent.h"

#endif // _BEHAVIAC_HEADERS_H_</pre>
<p>注意上图中左下方的选项“生成代码时使用相对路径”，该选项用于生成上述包含头文件时，是否生成相对路径。</p>
<p>如果已经在自己的代码项目中设置了包含路径，可以不勾选该选项，生成的代码如下所示：</p>
<pre>#ifndef _BEHAVIAC_HEADERS_H_
#define _BEHAVIAC_HEADERS_H_

#include "behaviac/behaviac.h"

// YOU SHOULD SET THE HEADER FILES OF YOUR GAME WHEN EXPORTING CPP FILES ON THE BEHAVIAC EDITOR:
#include "SecondAgent.h"

#endif // _BEHAVIAC_HEADERS_H_</pre>
<h2><span class="ez-toc-section" id="7">7. 手工编辑类型信息</span></h2>
<p>有的程序员可能不喜欢使用类型信息浏览器来编辑类型信息，那么可以编写自己的导出工具或者直接手工编辑类型信息文件*.meta.xml。</p>
<p>该文件保存在工作区配置的“行为树源位置”中的behaviac_meta文件夹中，例如本教程对应的类型信息文件tutorial_1_2_cpp.meta.xml就在源码包tutorials/tutorial_1_2/workspace/behaviors/behaviac_meta目录下，该文件的内容如下：</p>
<p><img class="aligncenter size-full wp-image-1767" src="/wp-content/uploads/2017/03/8J8NL0R4A67G0CX3.png" alt="" width="980" height="496" srcset="/wp-content/uploads/2017/03/8J8NL0R4A67G0CX3.png 980w, /wp-content/uploads/2017/03/8J8NL0R4A67G0CX3-300x152.png 300w, /wp-content/uploads/2017/03/8J8NL0R4A67G0CX3-768x389.png 768w" sizes="(max-width: 980px) 100vw, 980px" /></p>
<p>可以手工编辑该文件，根据自己的需要添加或修改自己的类型信息，但需要确保内容格式跟上图保持一致，没有任何错误，否则会加载失败。</p>
<p>此外，编辑器还支持加载多个类型信息文件，支持混用编辑器编辑的类型信息和通过自己编写导出工具或手工编辑生成的类型信息这两种方式，那么可以将自己生成的*.meta.xml文件，也放在行为树源位置中的behaviac_meta目录里，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1768" src="/wp-content/uploads/2017/03/2TP6N2E2VD7A6SM2U.png" alt="" width="208" height="166" /></p>
<p>重新加载工作区后，会弹出如下提示窗口：</p>
<p id="DcUtgIe"><img class="size-full wp-image-1765 aligncenter" src="/wp-content/uploads/2017/03/img_58be862955972.png" alt="" srcset="/wp-content/uploads/2017/03/img_58be862955972.png 450w, /wp-content/uploads/2017/03/img_58be862955972-300x113.png 300w" sizes="(max-width: 450px) 100vw, 450px" /></p>
<p>如果没有弹出上述提示窗口，说明已经合并过多个类型信息文件，可以打开工作区文件tutorial_1_2_cpp.workspace.xml，并修改promptmergingmeta的值为&#8221;false&#8221;，如下图所示：</p>
<p id="TLuyFmk"><img class="aligncenter size-full wp-image-1769" src="/wp-content/uploads/2017/03/F4E714S7R_DDVXBXEAA4E.png" alt="" width="1159" height="266" srcset="/wp-content/uploads/2017/03/F4E714S7R_DDVXBXEAA4E.png 1159w, /wp-content/uploads/2017/03/F4E714S7R_DDVXBXEAA4E-300x69.png 300w, /wp-content/uploads/2017/03/F4E714S7R_DDVXBXEAA4E-768x176.png 768w, /wp-content/uploads/2017/03/F4E714S7R_DDVXBXEAA4E-1024x235.png 1024w" sizes="(max-width: 1159px) 100vw, 1159px" /></p>
<p>重新加载工作区，会再次弹出上述提示窗口。点击”是(Y)“，编辑器会自动合并多个类型信息文件。</p>
<p>这样，在类型信息浏览器中就可以查看手工编辑的所有类型信息，并在行为树中使用这些类型信息了。</p>
<h2><span class="ez-toc-section" id="8">8. 添加行为树</span></h2>
<p>利用新加的SecondAgent类及其成员属性和方法，添加行为树&#8221;SecondBT&#8221;，如下图所示：<img class="aligncenter size-full wp-image-1758" src="/wp-content/uploads/2017/03/RLZW3DYRV77JR4GKH_3B.png" alt="" width="905" height="283" srcset="/wp-content/uploads/2017/03/RLZW3DYRV77JR4GKH_3B.png 905w, /wp-content/uploads/2017/03/RLZW3DYRV77JR4GKH_3B-300x94.png 300w, /wp-content/uploads/2017/03/RLZW3DYRV77JR4GKH_3B-768x240.png 768w" sizes="(max-width: 905px) 100vw, 905px" /></p>
<h2><span class="ez-toc-section" id="9">9. 执行行为树</span></h2>
<p>加载并执行该行为树，可以看到输出结果如下图所示：</p>
<p id="TzfBzAW"><img class="size-full wp-image-1759 aligncenter" src="/wp-content/uploads/2017/03/img_58be770452f3d.png" alt="" /></p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_1_2">tutorials/tutorial_1_2</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_1_2_write_codes/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>教程2：让行为树丰富起来</title>
		<link>/tutorial_2_more_nodes/</link>
					<comments>/tutorial_2_more_nodes/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Fri, 20 Jan 2017 04:08:48 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1492</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 类似于任何一种程序语言的基本语法，behaviac组件也提供了基本的赋值、条件、<a class="moretag" href="/tutorial_2_more_nodes/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>类似于任何一种程序语言的基本语法，behaviac组件也提供了基本的赋值、条件、循环、序列、选择等基本节点。有了《<a href="/tutorial_1_hello_behaviac/">教程1：Hello Behaviac</a>》的基本介绍，本教程将引入这些常用的复合节点，以便将行为树编辑得更加丰富多彩。</p>
<p>用编辑器打开本教程C++版的工作区文件<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_2/workspace/tutorial_2_cpp.workspace.xml">tutorial_2_cpp.workspace.xml</a>（而C#版工作区文件是<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_2/workspace/tutorial_2_cs.workspace.xml">tutorial_2_cs.workspace.xml</a>），如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1578" src="/wp-content/uploads/2017/01/tutorial_2_cpp_workspace.png" alt="" width="587" height="272" srcset="/wp-content/uploads/2017/01/tutorial_2_cpp_workspace.png 587w, /wp-content/uploads/2017/01/tutorial_2_cpp_workspace-300x139.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<p>注意：本教程延用了《<a href="/tutorial_1_hello_behaviac/">教程一</a>》的FirstAgent子类及其成员方法SayHello等类型信息，可以参考《<a href="/tutorial_1_hello_behaviac/">教程一</a>》的做法，打开类型信息浏览器创建该子类。此外，还为FirstAgent子类添加了int类型的成员属性p1，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1493" src="/wp-content/uploads/2017/01/p1.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/01/p1.png 612w, /wp-content/uploads/2017/01/p1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>参考《<a href="/tutorial_1_hello_behaviac/">教程一</a>》的做法，点击上图中右下方的“应用”按钮，生成“胶水”代码，并将这些代码整合到项目tutorial_2中，并添加tutorial_2.cpp文件用于使用behaviac的相关接口来加载和执行行为树，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1579" src="/wp-content/uploads/2017/01/tutorial_2_cpp_project.png" alt="" width="378" height="343" srcset="/wp-content/uploads/2017/01/tutorial_2_cpp_project.png 378w, /wp-content/uploads/2017/01/tutorial_2_cpp_project-300x272.png 300w" sizes="(max-width: 378px) 100vw, 378px" /></p>
<h2><span class="ez-toc-section" id="i">循环节点</span></h2>
<p>循环节点类似于程序语言中的for或while循环，用于重复执行某个操作。</p>
<p>新建行为树“LoopBT”，将根节点的Agent类型设置为“FirstAgent”，并为其添加循环和动作节点，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1495" src="/wp-content/uploads/2017/01/loop_node.png" alt="" width="130" height="370" srcset="/wp-content/uploads/2017/01/loop_node.png 130w, /wp-content/uploads/2017/01/loop_node-105x300.png 105w" sizes="(max-width: 130px) 100vw, 130px" /></p>
<p><img class="aligncenter size-full wp-image-1496" src="/wp-content/uploads/2017/01/loop_bt.png" alt="" width="828" height="137" srcset="/wp-content/uploads/2017/01/loop_bt.png 828w, /wp-content/uploads/2017/01/loop_bt-300x50.png 300w, /wp-content/uploads/2017/01/loop_bt-768x127.png 768w" sizes="(max-width: 828px) 100vw, 828px" /></p>
<p>选中循环节点，将其参数“次数”设置为3，其他参数暂不用设置，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1497" src="/wp-content/uploads/2017/01/loop_properties.png" alt="" width="474" height="213" srcset="/wp-content/uploads/2017/01/loop_properties.png 474w, /wp-content/uploads/2017/01/loop_properties-300x135.png 300w" sizes="(max-width: 474px) 100vw, 474px" /></p>
<p>选中动作节点，为其选择“SayHello”方法，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1322" src="/wp-content/uploads/2016/12/action_properties.png" alt="" width="476" height="102" srcset="/wp-content/uploads/2016/12/action_properties.png 476w, /wp-content/uploads/2016/12/action_properties-300x64.png 300w" sizes="(max-width: 476px) 100vw, 476px" /></p>
<p>导出、加载并执行该行为树“LoopBT”，得到如下图所示的结果：</p>
<p><img class="aligncenter size-full wp-image-1498" src="/wp-content/uploads/2017/01/loop_bt_result.png" alt="" width="157" height="210" /></p>
<p>可以看到输出了3次“Hello Behaviac!”，这是我们预期的结果。</p>
<p>如果想了解循环节点其他参数的用法，请选中循环节点，并按F1键，会自动打开该节点的使用手册。</p>
<p>此外，循环直到节点类似于循环节点，两者的差别可以参考手册《<a href="/language/zh/decorator/#loopuntil">循环直到节点</a>》和《<a href="/language/zh/decorator/#loop">循环节点</a>》。</p>
<h2><span class="ez-toc-section" id="i-2">赋值节点</span></h2>
<p>新建行为树“SequenceBT”，将根节点的Agent类型设置为“FirstAgent”，并为其依次添加序列、赋值、条件和动作节点，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1500" src="/wp-content/uploads/2017/01/sequence_bt_nodes.png" alt="" width="121" height="371" srcset="/wp-content/uploads/2017/01/sequence_bt_nodes.png 121w, /wp-content/uploads/2017/01/sequence_bt_nodes-98x300.png 98w" sizes="(max-width: 121px) 100vw, 121px" /></p>
<p><img class="aligncenter size-full wp-image-1501" src="/wp-content/uploads/2017/01/sequence_bt.png" alt="" width="853" height="293" srcset="/wp-content/uploads/2017/01/sequence_bt.png 853w, /wp-content/uploads/2017/01/sequence_bt-300x103.png 300w, /wp-content/uploads/2017/01/sequence_bt-768x264.png 768w" sizes="(max-width: 853px) 100vw, 853px" /></p>
<p>类似于程序语言中的赋值语句，赋值节点可以将右值赋给左值。</p>
<p>选中上图中的赋值节点，将“左参数”选择为前面所添加的成员属性“p1”，“右参数”直接设置为6，表示程序端在执行该行为树时，会将右值6赋给左值p1，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1502" src="/wp-content/uploads/2017/01/assignment_properties.png" alt="" width="477" height="212" srcset="/wp-content/uploads/2017/01/assignment_properties.png 477w, /wp-content/uploads/2017/01/assignment_properties-300x133.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>更多细节请参考手册《<a href="/language/zh/assignment/">赋值节点</a>》。</p>
<h2><span class="ez-toc-section" id="i-3">条件节点</span></h2>
<p>类似于程序语言中的条件判断语句，条件节点用于比较两个值的情况，用于跟后续节点组合使用，表示条件满足时，是否执行后续的节点。</p>
<p>选中上面行为树“SequenceBT”中的条件节点，将“左参数”选择为前面所添加的成员属性“p1”，“右参数”直接设置为3，“操作符”设置为“&gt;”，表示判断p1是否大于3，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1503" src="/wp-content/uploads/2017/01/condition_properties.png" alt="" width="477" height="214" srcset="/wp-content/uploads/2017/01/condition_properties.png 477w, /wp-content/uploads/2017/01/condition_properties-300x135.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>更多细节请参考手册《<a href="/language/zh/condition/">条件节点</a>》。</p>
<h2><span class="ez-toc-section" id="i-4">序列节点</span></h2>
<p>序列节点是行为树中传统的组合节点之一。该节点以给定的顺序依次执行其子节点，直到所有子节点成功返回，该节点也返回成功。只要其中某个子节点失败，那么该节点就直接返回失败，不再执行后续的子节点。</p>
<p>在上面行为树“SequenceBT”中，可以看到序列节点有3个子节点，分别是赋值、条件和动作节点。在依次执行该序列节点的子节点时，赋值节点（p1 = 6）永远返回成功，将继续执行条件节点（p1 &gt; 3），该条件节点也返回成功，因此继续执行动作节点（SayHello），最后期望输出“Hello Behaviac!”。</p>
<p>执行该行为树，得到如下结果：</p>
<p><img class="aligncenter size-full wp-image-1504" src="/wp-content/uploads/2017/01/sequence_bt_result.png" alt="" width="191" height="81" /></p>
<p>可以看到，执行结果跟期望保持一致。</p>
<p>如果将条件节点的右值3改为8，得到行为树如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1505" src="/wp-content/uploads/2017/01/sequence_bt_8.png" alt="" width="851" height="287" srcset="/wp-content/uploads/2017/01/sequence_bt_8.png 851w, /wp-content/uploads/2017/01/sequence_bt_8-300x101.png 300w, /wp-content/uploads/2017/01/sequence_bt_8-768x259.png 768w" sizes="(max-width: 851px) 100vw, 851px" /></p>
<p>重新导出并加载执行该行为树，执行结果如下所示：</p>
<p><img class="aligncenter size-full wp-image-1506" src="/wp-content/uploads/2017/01/sequence_bt_8_result.png" alt="" width="198" height="56" /></p>
<p>可以看到，并没有输出“Hello Behaviac!”，说明动作节点（SayHello）没有得到执行，因为条件节点（p1 &gt; 8）已经返回失败。</p>
<p>更多细节请参考手册《<a href="/language/zh/sequence/">序列节点</a>》。</p>
<h2><span class="ez-toc-section" id="i-5">选择节点</span></h2>
<p>选择节点也是行为树中传统的组合节点之一。该节点以给定的顺序依次调用其子节点，直到其中一个成功返回，那么该节点也直接返回成功，不再执行后续的子节点。如果所有的子节点都失败，那么该节点也返回失败。</p>
<p>新建行为树“SelectBT”，将根节点的Agent类型设置为“FirstAgent”，并为其依次添加序列、赋值、选择、条件和动作节点，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1507" src="/wp-content/uploads/2017/01/select_bt_nodes.png" alt="" width="124" height="372" srcset="/wp-content/uploads/2017/01/select_bt_nodes.png 124w, /wp-content/uploads/2017/01/select_bt_nodes-100x300.png 100w" sizes="(max-width: 124px) 100vw, 124px" /></p>
<p><img class="aligncenter size-full wp-image-1508" src="/wp-content/uploads/2017/01/select_bt.png" alt="" width="1095" height="282" srcset="/wp-content/uploads/2017/01/select_bt.png 1095w, /wp-content/uploads/2017/01/select_bt-300x77.png 300w, /wp-content/uploads/2017/01/select_bt-768x198.png 768w, /wp-content/uploads/2017/01/select_bt-1024x264.png 1024w" sizes="(max-width: 1095px) 100vw, 1095px" /></p>
<p>执行该行为树，得到结果如下：</p>
<p><img class="aligncenter size-full wp-image-1509" src="/wp-content/uploads/2017/01/select_bt_result.png" alt="" width="178" height="54" /></p>
<p>可以看到，并没有输出“Hello Behaviac!”，说明动作节点（SayHello）没有得到执行，因为条件节点（p1 &gt; 3）已经返回成功，那么选择节点直接返回成功，不再执行后续的子节点。</p>
<p>如果将条件节点的右值3改为8，得到如下的行为树：</p>
<p><img class="aligncenter size-full wp-image-1510" src="/wp-content/uploads/2017/01/select_bt_8.png" alt="" width="1101" height="287" srcset="/wp-content/uploads/2017/01/select_bt_8.png 1101w, /wp-content/uploads/2017/01/select_bt_8-300x78.png 300w, /wp-content/uploads/2017/01/select_bt_8-768x200.png 768w, /wp-content/uploads/2017/01/select_bt_8-1024x267.png 1024w" sizes="(max-width: 1101px) 100vw, 1101px" /></p>
<p>重新导出并加载执行该行为树，执行结果如下所示：</p>
<p><img class="aligncenter size-full wp-image-1511" src="/wp-content/uploads/2017/01/select_bt_8_result.png" alt="" width="174" height="87" /></p>
<p>可以看到，执行结果输出了“Hello Behaviac!”，说明动作节点（SayHello）得到了执行，因为条件节点（p1 &gt; 8）返回失败，选择节点会继续执行后续的子节点，也就是该动作节点。</p>
<p>更多细节请参考手册《<a href="/language/zh/selector/">选择节点</a>》。</p>
<h2><span class="ez-toc-section" id="i-6">导出格式</span></h2>
<p>除了支持《<a href="/tutorial_1_hello_behaviac/">教程一</a>》介绍的XML导出格式，behaviac组件还支持BSON、C++和C#格式的行为树导出。</p>
<p>勾选上所有的导出格式，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1518" src="/wp-content/uploads/2017/01/export_formats.png" alt="" width="395" height="595" srcset="/wp-content/uploads/2017/01/export_formats.png 395w, /wp-content/uploads/2017/01/export_formats-199x300.png 199w" sizes="(max-width: 395px) 100vw, 395px" /></p>
<h3><span class="ez-toc-section" id="XML">XML</span></h3>
<p>指定文件格式为XML，如下代码所示：</p>
<pre>behaviac::Workspace::GetInstance()-&gt;SetFileFormat(behaviac::Workspace::EFF_xml);</pre>
<h3><span class="ez-toc-section" id="BSON">BSON</span></h3>
<p>点击右下方的“导出”按钮后，可以看到在导出目录tutorials/tutorial_2/cpp/exported下，除了原有的*.xml文件之外，还有了*.bson.bytes文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1521" src="/wp-content/uploads/2017/01/export_bson.png" alt="" width="208" height="271" /></p>
<p>加载使用BSON文件，只需要把文件格式改为BSON即可，如下代码所示：</p>
<pre>behaviac::Workspace::GetInstance()-&gt;SetFileFormat(behaviac::Workspace::EFF_bson);</pre>
<p>加载某个行为树时，文件名并不需要指定后缀，只要指定相对于导出位置的路径和文件名，如下代码所示：</p>
<pre>g_FirstAgent-&gt;btload(“LoopBT”);</pre>
<p>这里，我们使用行为树“LoopBT”，执行后的结果如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1498" src="/wp-content/uploads/2017/01/loop_bt_result.png" alt="" width="157" height="210" /></p>
<p>可以看出，跟XML格式的执行结果保持一致。</p>
<h3><span class="ez-toc-section" id="C">C++</span></h3>
<p>在代码生成目录tutorials/tutorial_2/cpp/behaviac_generated/behaviors下，导出了行为树的C++源码文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1523" src="/wp-content/uploads/2017/01/export_cpp.png" alt="" width="268" height="165" /></p>
<p>需要把这些文件整合到自己的项目中一起编译，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1580" src="/wp-content/uploads/2017/01/tutorial_2_cpp_generated_project.png" alt="" width="385" height="381" srcset="/wp-content/uploads/2017/01/tutorial_2_cpp_generated_project.png 385w, /wp-content/uploads/2017/01/tutorial_2_cpp_generated_project-300x297.png 300w" sizes="(max-width: 385px) 100vw, 385px" /></p>
<p>所有C++版教程的项目都包含在源码包中projects/vs2013目录中的工程behaviac.sln，打开该工程文件后，可以看到里面有behaviac组件的源码和所有的教程项目，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1581" src="/wp-content/uploads/2017/01/tutorial_projects.png" alt="" width="144" height="178" /></p>
<p>找到tutorial_2项目，打开里面的tutorial_2.cpp文件，将文件格式改为C++，如下代码所示：</p>
<pre>behaviac::Workspace::GetInstance()-&gt;SetFileFormat(behaviac::Workspace::EFF_cpp);</pre>
<p>这里，我们使用行为树“LoopBT”，执行后的结果如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1498" src="/wp-content/uploads/2017/01/loop_bt_result.png" alt="" width="157" height="210" /></p>
<p>可以看出，跟XML格式的执行结果保持一致。</p>
<h3><span class="ez-toc-section" id="C-2">C#</span></h3>
<p>打开本教程C#版的工作区文件tutorials/tutorial_2/workspace/tutorial_2_cs.workspace.xml，该工作区的参数配置如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1582" src="/wp-content/uploads/2017/01/tutorial_2_cs_workspace.png" alt="" width="587" height="272" srcset="/wp-content/uploads/2017/01/tutorial_2_cs_workspace.png 587w, /wp-content/uploads/2017/01/tutorial_2_cs_workspace-300x139.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<p>类似于前面介绍的导出窗口配置，选中所有的格式并进行导出，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1528" src="/wp-content/uploads/2017/01/export_all_cs.png" alt="" width="395" height="595" srcset="/wp-content/uploads/2017/01/export_all_cs.png 395w, /wp-content/uploads/2017/01/export_all_cs-199x300.png 199w" sizes="(max-width: 395px) 100vw, 395px" /></p>
<p>打开位于源码包tutorials/tutorial_2/cs目录中的tutorial_2.sln工程，可以查看本教程的C#示例代码。</p>
<p>可以通过修改文件格式来加载不同类型的行为树文件，如下代码所示：</p>
<p>加载XML版的行为树：</p>
<pre>behaviac.Workspace.Instance.FileFormat = behaviac.Workspace.EFileFormat.EFF_xml;</pre>
<p>加载BSON版的行为树：</p>
<pre>behaviac.Workspace.Instance.FileFormat = behaviac.Workspace.EFileFormat.EFF_bson;</pre>
<p>加载C#版的行为树：</p>
<pre>behaviac.Workspace.Instance.FileFormat = behaviac.Workspace.EFileFormat.EFF_cs;</pre>
<p>编译并执行C#工程，可以查看加载和执行行为树后的结果。</p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_2">tutorials/tutorial_2</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_2_more_nodes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程3：Agent实例</title>
		<link>/tutorial_3_agent_instance/</link>
					<comments>/tutorial_3_agent_instance/#comments</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Mon, 23 Jan 2017 03:54:28 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1534</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 我们知道，面向对象程序编程的定义就是使用对象来做设计，对象即是类的实例。beha<a class="moretag" href="/tutorial_3_agent_instance/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>我们知道，面向对象程序编程的定义就是使用对象来做设计，对象即是类的实例。behaviac组件是基于Agent类及其实例来运转的，Agent类的实例加载和执行行为树，而在行为树的节点中又有可能用到了Agent实例的成员属性或方法。</p>
<p>在编辑器的节点属性窗口中，为了给该节点配置参数，首先需要选择一个实例，然后再选择该实例的成员属性或方法，如下图所示：</p>
<p><img class="aligncenter" src="/img/tutorials/tutorial17/instance_list.png" alt="" /></p>
<p>这些实例来自于如下三个方面：</p>
<ul>
<li><strong>Self：</strong>当前行为树根节点所配置的Agent类的实例，类似于程序语言中的this。</li>
<li><strong>成员实例：</strong>当前行为树根节点所配置的Agent类的成员属性，或是当前行为树的局部变量，需要是Agent或其子类类型。</li>
<li><strong>全局实例：</strong>在类型信息浏览器中编辑并生成注册代码的各种Agent或其子类的全局变量。</li>
</ul>
<h2><span class="ez-toc-section" id="i">成员实例</span></h2>
<p>对于成员实例，在上图所示的节点属性窗口中会根据当前行为树根节点所配置的Agent类型，自动列举出所有的成员实例以供选择。但在使用该成员实例之前，需要确保该实例已经赋过值，而不是空指针或引用。</p>
<p>在类型信息浏览器中添加新的Agent子类SecondAgent，并为其添加一个int类型的成员属性p2，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1540" src="/wp-content/uploads/2017/01/second_agent.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/01/second_agent.png 612w, /wp-content/uploads/2017/01/second_agent-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>然后，为FirstAgent类添加SecondAgent类型的成员属性pInstance，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1541" src="/wp-content/uploads/2017/01/member_agent_instance.png" alt="" width="607" height="732" srcset="/wp-content/uploads/2017/01/member_agent_instance.png 607w, /wp-content/uploads/2017/01/member_agent_instance-249x300.png 249w" sizes="(max-width: 607px) 100vw, 607px" /></p>
<p>点击上图中的“确认”按钮后，可以看到FirstAgent类多了一个成员属性pInstance，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1543" src="/wp-content/uploads/2017/01/member_agent_instance_added.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/01/member_agent_instance_added.png 612w, /wp-content/uploads/2017/01/member_agent_instance_added-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2><span class="ez-toc-section" id="i-2">全局实例</span></h2>
<p>对于全局实例，各种Agent或其子类实例的名字注册和绑定是为了支持单件（Singleton）或者类似确定的全局性实例（同一个类可能会有若干个实例而不是仅仅有一个实例），如player、camera、director等。</p>
<p>点击类型信息浏览器中部的“实例名称”右侧的“新增”按钮，添加SecondAgent类型的全局实例SecondAgentInstance，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1542" src="/wp-content/uploads/2017/01/second_agent_instance.png" alt="" width="612" height="733" srcset="/wp-content/uploads/2017/01/second_agent_instance.png 612w, /wp-content/uploads/2017/01/second_agent_instance-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>点击上图中的“确认”按钮后，可以看到SecondAgent类的“实例名称”下拉列表中有了新加的全局实例SecondAgentInstance，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1544" src="/wp-content/uploads/2017/01/second_agent_instance_added.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/01/second_agent_instance_added.png 612w, /wp-content/uploads/2017/01/second_agent_instance_added-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>点击上图中右下方的“应用”按钮，就可以在行为树中分别使用这2个新加的成员实例和全局实例了。</p>
<h2><span class="ez-toc-section" id="i-3">应用</span></h2>
<p>新建一棵行为树“InstanceBT”，依次添加序列、赋值、条件和动作节点，并为根节点选择FirstAgent类型，将动作节点配置为Self及其成员方法SayHello，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1556" src="/wp-content/uploads/2017/01/instance_bt_empty-2.png" alt="" width="839" height="376" srcset="/wp-content/uploads/2017/01/instance_bt_empty-2.png 839w, /wp-content/uploads/2017/01/instance_bt_empty-2-300x134.png 300w, /wp-content/uploads/2017/01/instance_bt_empty-2-768x344.png 768w, /wp-content/uploads/2017/01/instance_bt_empty-2-604x270.png 604w" sizes="(max-width: 839px) 100vw, 839px" /></p>
<p>选中ID为1的赋值节点，在其属性窗口“左参数”的实例名中，可以为其选择Self、SecondAgentInstance和pInstance 3个实例了，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1557" src="/wp-content/uploads/2017/01/instance_bt_assignment.png" alt="" width="481" height="217" srcset="/wp-content/uploads/2017/01/instance_bt_assignment.png 481w, /wp-content/uploads/2017/01/instance_bt_assignment-300x135.png 300w" sizes="(max-width: 481px) 100vw, 481px" /></p>
<p>为其选择SecondAgentInstance及其成员属性p2，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1558" src="/wp-content/uploads/2017/01/instance_bt_assignment_set.png" alt="" width="477" height="213" srcset="/wp-content/uploads/2017/01/instance_bt_assignment_set.png 477w, /wp-content/uploads/2017/01/instance_bt_assignment_set-300x134.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>类似的，选中ID为2的赋值节点，为其选择pInstance及其成员属性p2，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1559" src="/wp-content/uploads/2017/01/instance_bt_assignment2_set.png" alt="" width="477" height="215" srcset="/wp-content/uploads/2017/01/instance_bt_assignment2_set.png 477w, /wp-content/uploads/2017/01/instance_bt_assignment2_set-300x135.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>选中ID为3的条件节点，将“左参数”选择为SecondAgentInstance及其成员属性p2，将“右参数”选择为pInstance及其成员属性p2，将“操作符”选择为“&gt;”，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1548" src="/wp-content/uploads/2017/01/instance_condition_set.png" alt="" width="453" height="213" srcset="/wp-content/uploads/2017/01/instance_condition_set.png 453w, /wp-content/uploads/2017/01/instance_condition_set-300x141.png 300w" sizes="(max-width: 453px) 100vw, 453px" /></p>
<p>配置完之后，得到行为树“InstanceBT”如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1560" src="/wp-content/uploads/2017/01/instance_bt_set-1.png" alt="" width="1024" height="372" srcset="/wp-content/uploads/2017/01/instance_bt_set-1.png 1024w, /wp-content/uploads/2017/01/instance_bt_set-1-300x109.png 300w, /wp-content/uploads/2017/01/instance_bt_set-1-768x279.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>导出行为树后，程序端就可以在加载和执行该行为树“InstanceBT”了。</p>
<h3><span class="ez-toc-section" id="C">C++版</span></h3>
<p>在源码包的tutorials/tutorial_3/cpp/tutorial_3.cpp文件中，定义了3个变量，如下代码所示：</p>
<pre>FirstAgent* g_FirstAgent = NULL;
SecondAgent* g_SecondAgent = NULL;
SecondAgent* g_ThirdAgent = NULL;</pre>
<p>其中，g_FirstAgent用于加载和执行行为树“InstanceBT”，g_SecondAgent用于赋值给g_FirstAgent的成员属性pInstance，g_ThirdAgent作为全局实例供行为树“InstanceBT”中的节点使用。这3个变量的初始化，如下代码所示：</p>
<pre>bool InitPlayer()
{
    LOGI("InitPlayer : %s\n", "InstanceBT");

    // 创建g_FirstAgent，并加载行为树“InstanceBT”
    g_FirstAgent = behaviac::Agent::Create&lt;FirstAgent&gt;();
    bool bRet = g_FirstAgent-&gt;btload("InstanceBT");
    g_FirstAgent-&gt;btsetcurrent("InstanceBT");

    // 创建g_SecondAgent，并将该实例赋给g_FirstAgent的成员pInstance
    g_SecondAgent = behaviac::Agent::Create&lt;SecondAgent&gt;();
    g_FirstAgent-&gt;SetSecondAgent(g_SecondAgent);

    // 创建g_ThirdAgent，并将"SecondAgentInstance"绑定给该实例
    g_ThirdAgent = behaviac::Agent::Create&lt;SecondAgent&gt;("SecondAgentInstance");

    return bRet;
}</pre>
<h3><span class="ez-toc-section" id="C-2">C#版</span></h3>
<p>在源码包的tutorials/tutorial_3/cs/tutorial_3.cs文件中，定义了3个变量，如下代码所示：</p>
<pre>static FirstAgent g_FirstAgent;
static SecondAgent g_SecondAgent;
static SecondAgent g_ThirdAgent;</pre>
<p>其中，g_FirstAgent用于加载和执行行为树“InstanceBT”，g_SecondAgent用于赋值给g_FirstAgent的成员属性pInstance，g_ThirdAgent作为全局实例供行为树“InstanceBT”中的节点使用。这3个变量的初始化，如下代码所示：</p>
<pre>static bool InitPlayer()
{
    Console.WriteLine("InitPlayer");

    // 创建g_FirstAgent，并加载行为树“InstanceBT”
    g_FirstAgent = new FirstAgent();
    bool bRet = g_FirstAgent.btload("InstanceBT");
    Debug.Assert(bRet);
    g_FirstAgent.btsetcurrent("InstanceBT");

    // 创建g_SecondAgent，并将该实例赋给g_FirstAgent的成员pInstance
    g_SecondAgent = new SecondAgent();
    g_FirstAgent._set_pInstance(g_SecondAgent);

    // 创建g_ThirdAgent，并将"SecondAgentInstance"绑定给该实例
    g_ThirdAgent = new SecondAgent();
    behaviac.Agent.BindInstance(g_ThirdAgent, "SecondAgentInstance");

    return bRet;
 }</pre>
<p>编译并执行，可以看到输出了“Hello Behaviac!”，说明行为树的执行结果符合我们的预期，Agent实例得到了正确的使用。</p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_3">tutorials/tutorial_3</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_3_agent_instance/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>教程4：预制的使用</title>
		<link>/tutorial_4_prefab/</link>
					<comments>/tutorial_4_prefab/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Thu, 16 Feb 2017 10:54:19 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1588</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 预制（Prefab）可以用来复用和实例化已有的行为树，如果只是直接复用行为树，预<a class="moretag" href="/tutorial_4_prefab/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>预制（Prefab）可以用来复用和实例化已有的行为树，如果只是直接复用行为树，预制跟引用子树的功能是一样的。</p>
<p>但是预制还可以用来定制个别节点的配置，称之为对预制的实例化。也即，如果一棵行为树用到了一棵预制行为树，那么可以局部修改某些节点，这些修改的节点不会跟着预制行为树的更新而同步更新。</p>
<p>首先新建一棵行为树“ParentBT”，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1709" src="/wp-content/uploads/2017/02/parentbt.png" alt="" width="1093" height="466" srcset="/wp-content/uploads/2017/02/parentbt.png 1093w, /wp-content/uploads/2017/02/parentbt-300x128.png 300w, /wp-content/uploads/2017/02/parentbt-768x327.png 768w, /wp-content/uploads/2017/02/parentbt-1024x437.png 1024w" sizes="(max-width: 1093px) 100vw, 1093px" /></p>
<p>在ID为2的序列节点上右键鼠标，弹出菜单，选择“另存为预制行为树”，表示准备将该序列节点为根节点的子树保存为一棵预制行为树，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1710" src="/wp-content/uploads/2017/02/save_as_prefab.png" alt="" width="820" height="611" srcset="/wp-content/uploads/2017/02/save_as_prefab.png 820w, /wp-content/uploads/2017/02/save_as_prefab-300x224.png 300w, /wp-content/uploads/2017/02/save_as_prefab-768x572.png 768w" sizes="(max-width: 820px) 100vw, 820px" /></p>
<p>在弹出的“另存为预制”窗口中，可以为当前的预制改名，然后点击“确认”按钮，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1711" src="/wp-content/uploads/2017/02/save_as_prefab_confirm.png" alt="" width="390" height="160" srcset="/wp-content/uploads/2017/02/save_as_prefab_confirm.png 390w, /wp-content/uploads/2017/02/save_as_prefab_confirm-300x123.png 300w" sizes="(max-width: 390px) 100vw, 390px" /></p>
<p>在编辑器左侧的行为树列表中，可以看到多了“pf_Sequence”节点，这就是刚刚保存出来的预制行为树，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1712" src="/wp-content/uploads/2017/02/behaviors_list.png" alt="" width="214" height="127" /></p>
<p>在“Prefabs”下面的所有预制行为树都可以直接拖拽到主视口中打开的行为树中使用，不过需要保证预制行为树跟主视口中打开的行为树的Agent类型保持兼容，也即要么类型相同，要么预制行为树的Agent类型是主视口中打开的行为树的Agent类型的基类。</p>
<p>双击打开预制行为树“pf_Sequence”，可以看到该树自动添加了根节点及其Agent类型“FirstAgent”，其他节点跟原有的情况保持一致，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1713" src="/wp-content/uploads/2017/02/pf_prefab.png" alt="" width="848" height="284" srcset="/wp-content/uploads/2017/02/pf_prefab.png 848w, /wp-content/uploads/2017/02/pf_prefab-300x100.png 300w, /wp-content/uploads/2017/02/pf_prefab-768x257.png 768w" sizes="(max-width: 848px) 100vw, 848px" /></p>
<p>而在行为树“ParentBT”中，可以看到原有的ID为2的序列节点所在的子树已被上面的预制行为树“pf_Sequence”所替代，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1714" src="/wp-content/uploads/2017/02/parentbt_prefab.png" alt="" width="1094" height="471" srcset="/wp-content/uploads/2017/02/parentbt_prefab.png 1094w, /wp-content/uploads/2017/02/parentbt_prefab-300x129.png 300w, /wp-content/uploads/2017/02/parentbt_prefab-768x331.png 768w, /wp-content/uploads/2017/02/parentbt_prefab-1024x441.png 1024w" sizes="(max-width: 1094px) 100vw, 1094px" /></p>
<p>修改了预制行为树“pf_Sequence”中的节点，所有引用到该预制行为树的行为树都会保持相同的更新，除非在行为树中有对预制行为树的节点属性有自己的修改或定制。</p>
<p>再为行为树“ParentBT”拖拽添加一个预制“pf_Sequence”分支，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1719" src="/wp-content/uploads/2017/02/prefab2.png" alt="" width="1040" height="691" srcset="/wp-content/uploads/2017/02/prefab2.png 1040w, /wp-content/uploads/2017/02/prefab2-300x199.png 300w, /wp-content/uploads/2017/02/prefab2-768x510.png 768w, /wp-content/uploads/2017/02/prefab2-1024x680.png 1024w" sizes="(max-width: 1040px) 100vw, 1040px" /></p>
<p>修改上图中的第二个预制“pf_Sequence”中ID为9的赋值节点右值为3，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1721" src="/wp-content/uploads/2017/02/prefab3-1.png" alt="" width="1037" height="691" srcset="/wp-content/uploads/2017/02/prefab3-1.png 1037w, /wp-content/uploads/2017/02/prefab3-1-300x200.png 300w, /wp-content/uploads/2017/02/prefab3-1-768x512.png 768w, /wp-content/uploads/2017/02/prefab3-1-1024x682.png 1024w" sizes="(max-width: 1037px) 100vw, 1037px" /></p>
<p>可以看到上图ID为8和9的两个节点都变为了虚线框，表示这是预制实例化（定制）后的节点及其父节点。</p>
<p>如果在预制行为树“pf_Sequence”中，修改节点ID为5的赋值节点的右值为6，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1722" src="/wp-content/uploads/2017/02/prefab4.png" alt="" width="844" height="280" srcset="/wp-content/uploads/2017/02/prefab4.png 844w, /wp-content/uploads/2017/02/prefab4-300x100.png 300w, /wp-content/uploads/2017/02/prefab4-768x255.png 768w" sizes="(max-width: 844px) 100vw, 844px" /></p>
<p>那么行为树“ParentBT”中ID为5的赋值节点的右值会同步更新为6，但是ID为9的赋值节点的右值还是为3，并没有同步更新，因为该节点已经被定制过了，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1723" src="/wp-content/uploads/2017/02/prefab5.png" alt="" width="1037" height="693" srcset="/wp-content/uploads/2017/02/prefab5.png 1037w, /wp-content/uploads/2017/02/prefab5-300x200.png 300w, /wp-content/uploads/2017/02/prefab5-768x513.png 768w, /wp-content/uploads/2017/02/prefab5-1024x684.png 1024w" sizes="(max-width: 1037px) 100vw, 1037px" /></p>
<p>执行最终的行为树，输出结果如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1715" src="/wp-content/uploads/2017/02/prefab_result.png" alt="" width="243" height="162" /></p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_4">tutorials/tutorial_4</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_4_prefab/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程5：子树的使用</title>
		<link>/tutorial_5_subtree/</link>
					<comments>/tutorial_5_subtree/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Fri, 17 Feb 2017 10:27:47 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1603</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 子树可以用来复用已有的行为树。通过子树节点，一个行为树可以作为另一个行为树的子树<a class="moretag" href="/tutorial_5_subtree/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>子树可以用来复用已有的行为树。通过<code class="highlighter-rouge">子树节点</code>，一个行为树可以作为另一个行为树的<code class="highlighter-rouge">子树，而</code>作为子树的那个行为树将被父树所“调用”。</p>
<p>子树还可以类似编程语言中的函数调用一样通过传递参数来使用。</p>
<p>类似动作节点，<code class="highlighter-rouge">子树</code>节点根据子树的执行结果也会返回一样的执行结果（即成功、失败或正在执行），其父节点按照自己的控制逻辑来控制接下来的运行。</p>
<h2><span class="ez-toc-section" id="1">1. 编辑类型信息</span></h2>
<p>首先，我们需要添加一个Agent类，后面会利用这个Agent类来创建行为树。</p>
<p>打开类型信息浏览器，分别为Agent类“FirstAgent”添加成员属性、方法和任务。</p>
<p>添加int类型的成员属性p1，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1608" src="/wp-content/uploads/2017/02/subtree_p1.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/02/subtree_p1.png 612w, /wp-content/uploads/2017/02/subtree_p1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>添加成员方法Say，该方法带有一个string&amp;类型的参数，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1624" src="/wp-content/uploads/2017/02/subtree_say-1.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/02/subtree_say-1.png 612w, /wp-content/uploads/2017/02/subtree_say-1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>添加任务t1，该任务带有一个int类型的参数，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1610" src="/wp-content/uploads/2017/02/subtree_t1.png" alt="" width="612" height="735" srcset="/wp-content/uploads/2017/02/subtree_t1.png 612w, /wp-content/uploads/2017/02/subtree_t1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2 id="section-3"><span class="ez-toc-section" id="2">2. 不带参数的子树</span></h2>
<p>首先给出子树最直接的用法——不带参数的子树：</p>
<p>首先，创建行为树“subtree”，将动作节点的方法Say的参数设置为“Hello subtree!”，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1612" src="/wp-content/uploads/2017/02/subtree-1.png" alt="" width="833" height="216" srcset="/wp-content/uploads/2017/02/subtree-1.png 833w, /wp-content/uploads/2017/02/subtree-1-300x78.png 300w, /wp-content/uploads/2017/02/subtree-1-768x199.png 768w" sizes="(max-width: 833px) 100vw, 833px" /></p>
<p>Say方法的功能是输出指定的字符串，如下代码所示：</p>
<pre>void FirstAgent::Say(behaviac::string&amp; param0)
{
///&lt;&lt;&lt; BEGIN WRITING YOUR CODE Say
    printf("\n%s\n\n", param0.c_str());
///&lt;&lt;&lt; END WRITING YOUR CODE
}</pre>
<p>然后，创建行为树“maintree”，并将行为树列表中的节点“subtree”直接拖拽到该树中，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1607" src="/wp-content/uploads/2017/02/subtrees-1.png" alt="" width="181" height="137" /></p>
<p><img class="aligncenter size-full wp-image-1613" src="/wp-content/uploads/2017/02/maintree-1.png" alt="" width="819" height="293" srcset="/wp-content/uploads/2017/02/maintree-1.png 819w, /wp-content/uploads/2017/02/maintree-1-300x107.png 300w, /wp-content/uploads/2017/02/maintree-1-768x275.png 768w" sizes="(max-width: 819px) 100vw, 819px" /></p>
<p>这样，行为树“maintree”就可以“调用”子树“subtree”了。</p>
<p>加载并执行行为树“maintree”后，结果如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1619" src="/wp-content/uploads/2017/02/hello_maintree.png" alt="" width="180" height="119" /></p>
<p>可以看到，输出了“Hello subtree!”字符串，说明子树“subtree”得到了正确的调用和执行。</p>
<h2><span class="ez-toc-section" id="3">3. 带参数的子树</span></h2>
<p>有时候，我们可能需要给子树传递参数来使用，这样子树会更加模块化。</p>
<p>对于这种需要传参的子树，可以按照如下操作进行：</p>
<p>首先，创建行为树“subtree_task”，并为其添加的第一个子节点必须是任务节点，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1615" src="/wp-content/uploads/2017/02/task_node.png" alt="" width="161" height="372" srcset="/wp-content/uploads/2017/02/task_node.png 161w, /wp-content/uploads/2017/02/task_node-130x300.png 130w" sizes="(max-width: 161px) 100vw, 161px" /></p>
<p><img class="aligncenter size-full wp-image-1614" src="/wp-content/uploads/2017/02/subtree_task.png" alt="" width="1140" height="196" srcset="/wp-content/uploads/2017/02/subtree_task.png 1140w, /wp-content/uploads/2017/02/subtree_task-300x52.png 300w, /wp-content/uploads/2017/02/subtree_task-768x132.png 768w, /wp-content/uploads/2017/02/subtree_task-1024x176.png 1024w" sizes="(max-width: 1140px) 100vw, 1140px" /></p>
<p>为上图中的任务节点，在其属性窗口中配置其“任务”参数为“t1”，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1628" src="/wp-content/uploads/2017/02/subtree_task_t1.png" alt="" width="477" height="102" srcset="/wp-content/uploads/2017/02/subtree_task_t1.png 477w, /wp-content/uploads/2017/02/subtree_task_t1-300x64.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>由于任务“t1”带有参数“param0”，所以在上面行为树“subtree_task”的条件节点中可以使用该参数“param0”，如上图所示。可以借鉴程序语言的说法，该参数“param0”就类似于函数的形参。</p>
<p>然后，创建行为树“maintree_task”，并将行为树列表中的节点“subtree_task”直接拖拽到该树中，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1607" src="/wp-content/uploads/2017/02/subtrees-1.png" alt="" width="181" height="137" /></p>
<p><img class="aligncenter size-full wp-image-1616" src="/wp-content/uploads/2017/02/maintree_task.png" alt="" width="867" height="296" srcset="/wp-content/uploads/2017/02/maintree_task.png 867w, /wp-content/uploads/2017/02/maintree_task-300x102.png 300w, /wp-content/uploads/2017/02/maintree_task-768x262.png 768w" sizes="(max-width: 867px) 100vw, 867px" /></p>
<p>选中上图中的子树节点，配置任务的参数值“param0”为2（这个参数类似于函数中的实参），如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1617" src="/wp-content/uploads/2017/02/task_set.png" alt="" width="475" height="163" srcset="/wp-content/uploads/2017/02/task_set.png 475w, /wp-content/uploads/2017/02/task_set-300x103.png 300w" sizes="(max-width: 475px) 100vw, 475px" /></p>
<p>这样，行为树“maintree_task”就可以“调用”子树“subtree_task”，并为该子树传递参数了。</p>
<p>加载并执行行为树“maintree_task”后，结果如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1621" src="/wp-content/uploads/2017/02/hello_maintree_task.png" alt="" width="218" height="121" /></p>
<p>可以看到，输出了“Hello subtree_task!”字符串，说明子树“subtree_task”得到了正确的调用和执行。</p>
<h2 id="section-3"><span class="ez-toc-section" id="4"><span id="i-4" class="ez-toc-section">4. 添加子树节点的补充说明</span></span></h2>
<ul>
<li>如上所述，可以从编辑器左侧的行为树节点列表中，通过鼠标选择并拖拽一棵行为树到另一棵行为树中来生成子树节点。被拖拽的行为树的路径被设置到<code class="highlighter-rouge">引用文件名</code>。需要指出的是，并非任意一个行为树都可以作为另外一个行为树的子树。3.6.32及之前版本，作为子树的Agent类型必须是父树的Agent类型的同类或父类。而3.6.33及之后版本，作为子树的Agent类型可以是父树的Agent类型的同类或父类或子类，但是需要保证执行该父树的Agent实例是父树和子树的Agent类型的子类或更低子类的实例（例如，假设父树的Agent类型是A，子树的Agent类型是B：如果A是B的子类，那么执行该父树的Agent实例必须是A或者A的子类的实例；如果B是A的子类，那么执行该父树的Agent实例必须是B或者B的子类的实例）。</li>
<li>另外，也可以像添加其他节点那样，在节点列表中选取子树，拖拽到相应的位置，然后点击该子树节点，在右侧的属性窗口中配置<code class="highlighter-rouge">引用文件名</code>或<code class="highlighter-rouge">任务</code>。<br />
<img src="/img/references/nodelist_subtree.png" alt="" /></li>
<li>如果手工配置的子树的路径是空的或无效的，在检查错误时会报错，表示该树不允许被导出。如果配置的是属性或方法，在编辑器中无法知其是否有效，只有运行的时候才会报运行时错误，如果运行过程中该值无效。</li>
</ul>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_5">tutorials/tutorial_5</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_5_subtree/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程6：事件的使用</title>
		<link>/tutorial_6_event_usage/</link>
					<comments>/tutorial_6_event_usage/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Thu, 16 Mar 2017 07:57:59 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1790</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 事件（Event）作为节点一种的附件，主要用于在程序端的游戏逻辑发出事件时，得到<a class="moretag" href="/tutorial_6_event_usage/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>事件（Event）作为节点一种的附件，主要用于在程序端的游戏逻辑发出事件时，得到响应后打断当前正在执行的行为树，并切换到所设置的另一个行为树。</p>
<h2><span class="ez-toc-section" id="1">1. 添加类型信息及任务</span></h2>
<p>在类型信息浏览器中为类“FirstAgent”添加了event_task(int param0)这个任务，或者更形象的称之为“接口”，该任务带有一个int类型的param0参数，如下图所示：</p>
<p id="mtRjkNr"><img class="size-full wp-image-1791 aligncenter" src="/wp-content/uploads/2017/03/img_58ca306fcc299.png" alt="" srcset="/wp-content/uploads/2017/03/img_58ca306fcc299.png 612w, /wp-content/uploads/2017/03/img_58ca306fcc299-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2><span class="ez-toc-section" id="2">2. 创建带任务节点的子树</span></h2>
<p>创建行为树subtree_task，该树根节点的第一个子节点务必是任务节点，并为其配置上面添加的任务event_task，如下三图所示：</p>
<p><img class="aligncenter size-full wp-image-1793" src="/wp-content/uploads/2017/03/8WWKVQO0LWHWXNOPEDT.png" alt="" width="143" height="349" srcset="/wp-content/uploads/2017/03/8WWKVQO0LWHWXNOPEDT.png 143w, /wp-content/uploads/2017/03/8WWKVQO0LWHWXNOPEDT-123x300.png 123w" sizes="(max-width: 143px) 100vw, 143px" /></p>
<p><img class="aligncenter size-full wp-image-1795" src="/wp-content/uploads/2017/03/MO1AP1TMFHI1QP0JO7.png" alt="" width="1077" height="180" srcset="/wp-content/uploads/2017/03/MO1AP1TMFHI1QP0JO7.png 1077w, /wp-content/uploads/2017/03/MO1AP1TMFHI1QP0JO7-300x50.png 300w, /wp-content/uploads/2017/03/MO1AP1TMFHI1QP0JO7-768x128.png 768w, /wp-content/uploads/2017/03/MO1AP1TMFHI1QP0JO7-1024x171.png 1024w" sizes="(max-width: 1077px) 100vw, 1077px" /></p>
<p><img class="size-full wp-image-1794 aligncenter" src="/wp-content/uploads/2017/03/img_58ca3309e0052.png" alt="" srcset="/wp-content/uploads/2017/03/img_58ca3309e0052.png 478w, /wp-content/uploads/2017/03/img_58ca3309e0052-300x103.png 300w" sizes="(max-width: 478px) 100vw, 478px" /></p>
<p>在上面的行为树subtree_task中，ID为1的条件节点使用了任务event_task的参数param0。这类似于编程语言中的函数参数为函数体的代码提供了局部变量，<strong>任务节点中的参数也为当前的行为树提供了同名的局部变量，这些“局部变量”可以根据需要用于该行为树所有子节点，也就在行为树节点中使用了任务的参数。</strong></p>
<h2><span class="ez-toc-section" id="3">3. 创建带有事件的主树</span></h2>
<p>创建另一个行为树maintree_task，并将ID为4的动作节点的参数“决定状态的选项”设置为Running，用于模拟行为树一直持续执行在该动作节点上，如下二图所示：</p>
<p id="rbrFofZ"><img class="size-full wp-image-1798 aligncenter" src="/wp-content/uploads/2017/03/img_58ca39b0c1e17.png" alt="" srcset="/wp-content/uploads/2017/03/img_58ca39b0c1e17.png 874w, /wp-content/uploads/2017/03/img_58ca39b0c1e17-300x130.png 300w, /wp-content/uploads/2017/03/img_58ca39b0c1e17-768x333.png 768w" sizes="(max-width: 874px) 100vw, 874px" /></p>
<p id="pVASTrI"><img class="size-full wp-image-1797 aligncenter" src="/wp-content/uploads/2017/03/img_58ca391f2fc13.png" alt="" srcset="/wp-content/uploads/2017/03/img_58ca391f2fc13.png 477w, /wp-content/uploads/2017/03/img_58ca391f2fc13-300x148.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>接着，在编辑器左侧的行为树节点列表中，将行为树节点subtree_task通过鼠标拖拽到行为树maintree_task中的第一个序列节点上（注意：一般默认把事件附件放在根节点的第一个子节点上），这样该序列节点就有了一个事件附件，如下图所示：</p>
<p><img class="size-full wp-image-1799 aligncenter" src="/wp-content/uploads/2017/03/img_58ca3e1e61419.png" alt="" srcset="/wp-content/uploads/2017/03/img_58ca3e1e61419.png 869w, /wp-content/uploads/2017/03/img_58ca3e1e61419-300x129.png 300w, /wp-content/uploads/2017/03/img_58ca3e1e61419-768x330.png 768w" sizes="(max-width: 869px) 100vw, 869px" /></p>
<p>然后，为该事件设置参数，如下图所示：</p>
<p id="iiOgZFc"><img class="size-full wp-image-1800 aligncenter" src="/wp-content/uploads/2017/03/img_58ca3f6ce5ae1.png" alt="" srcset="/wp-content/uploads/2017/03/img_58ca3f6ce5ae1.png 478w, /wp-content/uploads/2017/03/img_58ca3f6ce5ae1-300x118.png 300w" sizes="(max-width: 478px) 100vw, 478px" /></p>
<p>其中，“触发一次”表示该事件是否只触发一次就不再起作用。</p>
<p>“触发模式”控制该事件触发后对当前行为树的影响以及被触发的子树结束时应该如何恢复，有转移（Transfer）和返回（Return）两个选项：</p>
<ul>
<li>转移：当子树结束时，当前行为树被中断和重置，该子树将被设置为当前行为树。</li>
<li>返回：当子树结束时，返回控制到之前打断的地方继续执行。当前行为树直接“压”到执行堆栈上而不被中断和重置，该子树被设置为当前行为树，当该子树结束时，原本的那棵行为树从执行堆栈上“弹出”，并从当初的节点恢复执行。</li>
</ul>
<h2><span class="ez-toc-section" id="4">4. 程序端发送事件</span></h2>
<p>最后，在程序端通过如下代码，将事件“event_task”发出，并指定所需的参数，如下代码所示：</p>
<pre>g_FirstAgent-&gt;FireEvent("event_task", 2);</pre>
<p>这样，在执行行为树maintree_task过程中，如果接收到事件event_task，那么该行为树中的事件附件event_task将得到响应和处理，行为树的执行就会从当前的maintree_task跳转到subtree_task。</p>
<pre><strong>注意</strong>：调用FireEvent的时候，只有处于Running状态的节点才会响应事件。这是为了允许不同分支在不同时机下，同样的事件可以触发不同的行为。比如同样是BeingHit，受伤或逃跑的时候可以分别对应不同的行为。如果不需要根据不同的节点响应不同的行为，只是需要响应事件，一般只需把事件配置在根节点的第一个子节点上（根节点同样需要是Running状态，非Running状态的节点没有机会响应事件）。</pre>
<h2><span class="ez-toc-section" id="5">5. 执行行为树</span></h2>
<p>执行行为树maintree_task，可以得到如下结果：</p>
<p id="CShGPGh"><img class="size-full wp-image-1801 aligncenter" src="/wp-content/uploads/2017/03/img_58ca452400f73.png" alt="" /></p>
<p>本教程对应的工作区和代码工程，请查看源码包中的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_6">tutorials/tutorial_6</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_6_event_usage/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程7：行为树的连调</title>
		<link>/tutorial_7_debug/</link>
					<comments>/tutorial_7_debug/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Fri, 17 Mar 2017 09:30:36 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1811</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 对于行为树的调试，behaviac提供了连调和离线调试两大功能。 连调功能是在游<a class="moretag" href="/tutorial_7_debug/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>对于行为树的调试，behaviac提供了连调和离线调试两大功能。</p>
<p>连调功能是在游戏运行的时候，编辑器可以连上游戏，实时的查看树的运行情况、变量的当前值并可以设置断点等；而离线调试实际上是回放运行时所产生的log。</p>
<p>本教程主要介绍连调的过程和相关的功能说明，离线调试可以参考文章《<a href="/language/zh/debugging_desc/">调试功能的说明</a>》。</p>
<p>连调需要游戏是开发版本（即宏BEHAVIAC_RELEASE没有被定义），发布版本下没有连调的功能，可以参考文章《<a href="/language/zh/tutorial10_performence/">版本说明</a>》和《<a href="/language/zh/config/">开发功能开关</a>》。</p>
<p>打开目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_7/workspace">tutorials/tutorial_7/workspace</a>中的工作区，并打开类型信息浏览器，可以看到类FirstAgent有一个成员属性p1和两个成员方法Start和Wait，如下图所示：</p>
<p id="YtsrrmN"><img class="size-full wp-image-1813 aligncenter" src="/wp-content/uploads/2017/03/img_58cb9ab2eef0f.png" alt="" srcset="/wp-content/uploads/2017/03/img_58cb9ab2eef0f.png 612w, /wp-content/uploads/2017/03/img_58cb9ab2eef0f-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>点击上图右下方的应用按钮，在生成的FirstAgent.cpp文件中，填写Start和Wait的方法内容如下代码所示：</p>
<pre>void FirstAgent::Start()
{
///&lt;&lt;&lt; BEGIN WRITING YOUR CODE Start
    count = 0;
///&lt;&lt;&lt; END WRITING YOUR CODE
}

behaviac::EBTStatus FirstAgent::Wait()
{
///&lt;&lt;&lt; BEGIN WRITING YOUR CODE Wait
    count++;

    printf("p1 = %i\n", p1);

    if (count == 10000)
    {
        return behaviac::BT_SUCCESS;
    }

    return behaviac::BT_RUNNING;
///&lt;&lt;&lt; END WRITING YOUR CODE
}</pre>
<p>打开行为树demo，可以看到该行为树如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1812" src="/wp-content/uploads/2017/03/XK7N9TW1KUQYX2HA9958.png" alt="" width="1100" height="376" srcset="/wp-content/uploads/2017/03/XK7N9TW1KUQYX2HA9958.png 1100w, /wp-content/uploads/2017/03/XK7N9TW1KUQYX2HA9958-300x103.png 300w, /wp-content/uploads/2017/03/XK7N9TW1KUQYX2HA9958-768x263.png 768w, /wp-content/uploads/2017/03/XK7N9TW1KUQYX2HA9958-1024x350.png 1024w" sizes="(max-width: 1100px) 100vw, 1100px" /></p>
<p>为了在程序启动时，等待编辑器连接上才往后继续执行，需要在tutorial_7.cpp文件中的InitBehaviac方法中，添加如下代码：</p>
<pre>behaviac::Config::SetSocketBlocking(true);</pre>
<p>如果需要修改端口号，需要添加如下代码：</p>
<pre>behaviac::Config::SetSocketPort(60636);</pre>
<p>为了在连调时，程序端能够发送消息到编辑器端，需要在游戏循环中执行Workspace::DebugUpdate()方法，如下代码所示：</p>
<pre>void UpdateLoop()
{
    LOGI("UpdateLoop\n");

    int frames = 0;
    behaviac::EBTStatus status = behaviac::BT_RUNNING;

    while (status == behaviac::BT_RUNNING)
    {
        LOGI("frame %d\n", ++frames);

        behaviac::Workspace::GetInstance()-&gt;DebugUpdate();

        status = g_FirstAgent-&gt;btexec();
    }
}</pre>
<p>另外，如果程序端是通过Workspace::Update()的方式来统一执行所有Agent实例的行为树，则不需要再额外调用Workspace::DebugUpdate()方法，详见文章《<a href="/tutorial13_updateloop/">运行时端的执行流程</a>》。</p>
<p>启动程序，可以看到如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1814" src="/wp-content/uploads/2017/03/7H9AZWJN@HDGQGJ65A5.png" alt="" width="492" height="95" srcset="/wp-content/uploads/2017/03/7H9AZWJN@HDGQGJ65A5.png 492w, /wp-content/uploads/2017/03/7H9AZWJN@HDGQGJ65A5-300x58.png 300w" sizes="(max-width: 492px) 100vw, 492px" /></p>
<p>上面表示，程序端已经在开始等待编辑器的连接了。</p>
<p>点击编辑器工具栏中的“连接”按钮，如下图所示：</p>
<p id="RQIdnGB"><img class="size-full wp-image-1815 aligncenter" src="/wp-content/uploads/2017/03/img_58cba67af1592.png" alt="" /></p>
<p>在弹出的“连接游戏”窗口中，设置相应的IP和端口号后，点击“确认”按钮开始连接游戏，如下图所示：</p>
<p id="hKRboME"><img class="size-full wp-image-1816 aligncenter" src="/wp-content/uploads/2017/03/img_58cba7c708eff.png" alt="" srcset="/wp-content/uploads/2017/03/img_58cba7c708eff.png 322w, /wp-content/uploads/2017/03/img_58cba7c708eff-300x130.png 300w" sizes="(max-width: 322px) 100vw, 322px" /></p>
<p>编辑器成功连接后，在左侧的实例节点列表中，会列出当前的Agent实例，如下图所示：</p>
<p id="FwnCHwE"><img class="size-full wp-image-1817 aligncenter" src="/wp-content/uploads/2017/03/img_58cba86cda189.png" alt="" /></p>
<p>在“输出”窗口中，可以看到程序端发送过来的所有消息，编辑器也正是根据这些消息来相应的刷新当前的高亮执行路径和处理断点、刷新成员属性的当前值等，如下图所示：</p>
<p id="uENnzEu"><img class="size-full wp-image-1822 aligncenter" src="/wp-content/uploads/2017/03/img_58cbab8f124bd.png" alt="" srcset="/wp-content/uploads/2017/03/img_58cbab8f124bd.png 586w, /wp-content/uploads/2017/03/img_58cbab8f124bd-300x103.png 300w" sizes="(max-width: 586px) 100vw, 586px" /></p>
<p>鼠标双击实例节点列表中的节点FirstAgent_0_0，开始跟踪该实例的当前行为树的执行情况，可以看到行为树有了高亮的执行路径效果，表示当前返回Running的所有节点序列，如下图所示：</p>
<p id="LyMVOUW"><img class="size-full wp-image-1818 aligncenter" src="/wp-content/uploads/2017/03/img_58cba8ed9aff4.png" alt="" srcset="/wp-content/uploads/2017/03/img_58cba8ed9aff4.png 1107w, /wp-content/uploads/2017/03/img_58cba8ed9aff4-300x101.png 300w, /wp-content/uploads/2017/03/img_58cba8ed9aff4-768x258.png 768w, /wp-content/uploads/2017/03/img_58cba8ed9aff4-1024x344.png 1024w" sizes="(max-width: 1107px) 100vw, 1107px" /></p>
<p>双击某个节点的左侧可以为该节点添加“进入”断点，双击某个节点的右侧可以为该节点添加“退出”断点，如下图所示：</p>
<p id="xaOSRWe"><img class="size-full wp-image-1820 aligncenter" src="/wp-content/uploads/2017/03/img_58cbaac86b0af.png" alt="" srcset="/wp-content/uploads/2017/03/img_58cbaac86b0af.png 1102w, /wp-content/uploads/2017/03/img_58cbaac86b0af-300x103.png 300w, /wp-content/uploads/2017/03/img_58cbaac86b0af-768x263.png 768w, /wp-content/uploads/2017/03/img_58cbaac86b0af-1024x351.png 1024w" sizes="(max-width: 1102px) 100vw, 1102px" /></p>
<p>上图中高亮的断点，表示当前行为树的执行已经停在该处。点击Timeline工具栏中的“继续”按钮或直接按F5快捷键，可以继续执行行为树，如下图所示：</p>
<div>
<p id="dMOSqHw"><img class="size-full wp-image-1821 aligncenter" src="/wp-content/uploads/2017/03/img_58cbab355eaa5.png" alt="" srcset="/wp-content/uploads/2017/03/img_58cbab355eaa5.png 608w, /wp-content/uploads/2017/03/img_58cbab355eaa5-300x31.png 300w, /wp-content/uploads/2017/03/img_58cbab355eaa5-604x63.png 604w" sizes="(max-width: 608px) 100vw, 608px" /></p>
</div>
<p>在属性窗口中，可以查看当前实例的所有成员属性及其当前值，如下图所示：</p>
<p id="NgzRIhh"><img class="size-full wp-image-1823 aligncenter" src="/wp-content/uploads/2017/03/img_58cbac32b3d92.png" alt="" srcset="/wp-content/uploads/2017/03/img_58cbac32b3d92.png 829w, /wp-content/uploads/2017/03/img_58cbac32b3d92-300x30.png 300w, /wp-content/uploads/2017/03/img_58cbac32b3d92-768x77.png 768w" sizes="(max-width: 829px) 100vw, 829px" /></p>
<p>为了方便调试，可以在上图中手工修改属性的值，该值会被发送到程序端，影响行为树的执行。</p>
<p>有关连调的使用还可以参考<a href="http://bbs.behaviac.com/index.php/tag/%E8%BF%9E%E8%B0%83">连调相关常见问题</a>。</p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_7">tutorials/tutorial_7</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_7_debug/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程8：结构体的添加和使用</title>
		<link>/tutorial_8_extend_structs/</link>
					<comments>/tutorial_8_extend_structs/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Wed, 05 Apr 2017 10:16:42 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1861</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 对于结构体类型的使用，包括新增全新的结构体和扩展使用已有的结构体。对于新增的结构<a class="moretag" href="/tutorial_8_extend_structs/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>对于结构体类型的使用，包括新增全新的结构体和扩展使用已有的结构体。对于新增的结构体，又包括编辑器是否自动生成该结构体的代码。</p>
<p>实际上，我们将新增结构体，又不自动生成该结构体代码的情况，认为跟扩展使用已有的结构体是一致的，即都是在程序端已经有了该结构体的定义代码（要么手工编写，要么第三方代码已经包含了该结构体的定义），不用再让编辑器自动生成。</p>
<p>进而，后文将只通过<strong>“生成代码”</strong>和<strong>“不生成代码”</strong>来区分上面所说的各种使用情况，但这里需要注意的是，生成或不生成代码，只是针对结构体本身的定义而言，而结构体相关的“胶水”代码都是会自动生成的，并且必须要整合到自己的项目中一起编译构建。</p>
<p>1. 如果是“生成代码”的情况，则忽略这一步说明。否则，如果是“不生成代码”的情况，这里假定程序端已经有了结构体类型文件FirstStruct.h，该文件中包含了结构体“FirstStruct”的定义，如下代码所示：</p>
<pre>struct FirstStruct
{
    int s1;
    float s2;
};</pre>
<p>2. 在类型信息浏览器中新增跟程序端同名的结构体类型“FirstStruct”，并且根据自己的需要，来决定是否勾选“生成代码”选项（如果只是扩展使用已有的结构体，则不需要勾选），如下图所示：</p>
<p><img class="size-full wp-image-1863 aligncenter" src="/wp-content/uploads/2017/04/img_58e4aa4ded2fa.png" alt="" srcset="/wp-content/uploads/2017/04/img_58e4aa4ded2fa.png 368w, /wp-content/uploads/2017/04/img_58e4aa4ded2fa-300x219.png 300w" sizes="(max-width: 368px) 100vw, 368px" /></p>
<p>3. 上图中的“引用类型”选项，一般不用勾选，表示在行为树编辑器中可以为该结构体配置其成员属性，并且在该结构体的两个实例做比较运算时，会比较所有的成员属性。否则，如果勾选了“引用类型”选项，则表示该结构体在行为树中使用时是作为引用类型来使用，在该结构体的两个实例做比较运算时，只会比较两个实例的引用（指针），而不比较其内容（成员属性）。</p>
<p>4. 为结构体“FirstStruct”添加成员属性s1和s2，这跟程序端的定义保持一致，如下图所示：</p>
<p id="pxEYVoj"><img class="size-full wp-image-1864 aligncenter" src="/wp-content/uploads/2017/04/img_58e4afe7d87ff.png" alt="" srcset="/wp-content/uploads/2017/04/img_58e4afe7d87ff.png 612w, /wp-content/uploads/2017/04/img_58e4afe7d87ff-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>5. 对于C++版的运行时库，如果是“生成代码”的情况，则忽略这一步操作。否则，如果是“不生成代码”的情况，则说明程序端已经有了包含该结构体类型的头文件。点击上图右上方的“设置头文件”按钮，弹出“C++导出设置”窗口，并添加已有的结构体头文件FirstStruct.h，如下图所示：</p>
<p id="FOhtzdA"><img class="size-full wp-image-1866 aligncenter" src="/wp-content/uploads/2017/04/img_58e4b98a80a3b.png" alt="" srcset="/wp-content/uploads/2017/04/img_58e4b98a80a3b.png 524w, /wp-content/uploads/2017/04/img_58e4b98a80a3b-300x155.png 300w" sizes="(max-width: 524px) 100vw, 524px" /></p>
<p>6. 点击类型信息浏览器右下方的“应用”按钮，这样会在“代码生成位置”中生成该结构体的定义（如果上面勾选了“生成代码”选项）及相关的“胶水”代码<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_8/cpp/behaviac_generated/types/internal/behaviac_customized_types.h">behaviac_customized_types.h</a>等文件，如下代码所示：</p>
<pre>BEHAVIAC_EXTEND_EXISTING_TYPE_EX(FirstStruct, false);
BEHAVIAC_DECLARE_TYPE_VECTOR_HANDLER(FirstStruct);

// 如下结构体的定义代码，会根据是否勾选了上面所说的“生成代码”选项来决定是否生成
 
struct FirstStruct
{
    int s1;
    float s2;
};

// 如下代码，不管是否勾选了“生成代码”选项，都会自动生成

BEHAVIAC_EXTEND_EXISTING_TYPE_EX(FirstStruct, false);
BEHAVIAC_DECLARE_TYPE_VECTOR_HANDLER(FirstStruct);

template&lt; typename SWAPPER &gt;
inline void SwapByteImplement(FirstStruct&amp; v)
{
    SwapByteImplement&lt; SWAPPER &gt;(v.s1);
    SwapByteImplement&lt; SWAPPER &gt;(v.s2);
}

namespace behaviac
{
    namespace PrivateDetails
    {
        template&lt;&gt;
        inline bool Equal(const FirstStruct&amp; lhs, const FirstStruct&amp; rhs)
        {
            return Equal(lhs.s1, rhs.s1)
                &amp;&amp; Equal(lhs.s2, rhs.s2);
         }
     }
}</pre>
<p>7. 为FirstAgent类新增成员属性p1，其类型是结构体FirstStruct，如下图所示：</p>
<p id="jMyHgCv"><img class="size-full wp-image-1871 aligncenter" src="/wp-content/uploads/2017/04/img_58e4cdeba978e.png" alt="" srcset="/wp-content/uploads/2017/04/img_58e4cdeba978e.png 612w, /wp-content/uploads/2017/04/img_58e4cdeba978e-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>8. 点击类型信息浏览器右下方的“应用”按钮，将“代码生成位置”中<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_8/cpp/behaviac_generated/types/">behaviac_generated/types</a>目录下所有生成的代码文件，添加到自己的项目中一起编译构建。</p>
<p>9. 新增行为树“StrcutBT”，并使用成员属性p1来赋值和做比较运算，如下图所示：</p>
<p id="LrmqVUt"><img class="size-full wp-image-1867 aligncenter" src="/wp-content/uploads/2017/04/img_58e4bce69495e.png" alt="" srcset="/wp-content/uploads/2017/04/img_58e4bce69495e.png 823w, /wp-content/uploads/2017/04/img_58e4bce69495e-300x112.png 300w, /wp-content/uploads/2017/04/img_58e4bce69495e-768x286.png 768w" sizes="(max-width: 823px) 100vw, 823px" /></p>
<p>10. 执行该行为树，得到如下执行结果：<br />
<img class="aligncenter size-full wp-image-1868" src="/wp-content/uploads/2017/04/HGQ3LJ5J22UE48BNU.png" alt="" width="179" height="145" /></p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_8">tutorials/tutorial_8</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_8_extend_structs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程9：枚举的添加和使用</title>
		<link>/tutorial_9_extend_enum/</link>
					<comments>/tutorial_9_extend_enum/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Mon, 10 Apr 2017 03:22:33 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1878</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 对于枚举类型的使用，包括新增全新的枚举和扩展使用已有的枚举。对于新增的枚举，又包<a class="moretag" href="/tutorial_9_extend_enum/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>对于枚举类型的使用，包括新增全新的枚举和扩展使用已有的枚举。对于新增的枚举，又包括编辑器是否自动生成该枚举的代码。</p>
<p>实际上，我们将新增枚举，又不自动生成该枚举代码的情况，认为跟扩展使用已有的枚举是一致的，即都是在程序端已经有了该枚举的定义代码（要么手工编写，要么第三方代码已经包含了该枚举的定义），不用再让编辑器自动生成。</p>
<p>进而，后文将只通过<strong>“生成代码”</strong>和<strong>“不生成代码”</strong>来区分上面所说的各种使用情况，但这里需要注意的是，生成或不生成代码，只是针对枚举本身的定义而言，而枚举相关的“胶水”代码都是会自动生成的，并且必须要整合到自己的项目中一起编译构建。</p>
<p>1. 如果是“生成代码”的情况，则忽略这一步说明。否则，如果是“不生成代码”的情况，这里假定程序端已经有了枚举类型文件FirstEnum.h，该文件中包含了枚举“FirstEnum”的定义，如下代码所示：</p>
<pre>enum FirstEnum
{
    e1,
    e2,
    e3
};</pre>
<p>2. 在类型信息浏览器中新增跟程序端同名的枚举类型“FirstEnum”，并且根据自己的需要，来决定是否勾选“生成代码”选项（如果只是扩展使用已有的枚举，则不需要勾选），如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1880" src="/wp-content/uploads/2017/04/UNTAFB25PBQRD_DMN.png" alt="" width="365" height="263" srcset="/wp-content/uploads/2017/04/UNTAFB25PBQRD_DMN.png 365w, /wp-content/uploads/2017/04/UNTAFB25PBQRD_DMN-300x216.png 300w" sizes="(max-width: 365px) 100vw, 365px" /></p>
<p>3. 为枚举“FirstEnum”添加成员e1、e2和e3，这跟程序端的定义保持一致，如下图所示：</p>
<p id="llHMYON"><img class="size-full wp-image-1889 aligncenter" src="/wp-content/uploads/2017/04/img_58eafbec92aca.png" alt="" srcset="/wp-content/uploads/2017/04/img_58eafbec92aca.png 612w, /wp-content/uploads/2017/04/img_58eafbec92aca-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>4. 对于C++版的运行时库，如果是“生成代码”的情况，则忽略这一步操作。否则，如果是“不生成代码”的情况，则说明程序端已经有了包含该枚举类型的头文件。点击上图右上方的“设置头文件”按钮，弹出“C++导出设置”窗口，并添加已有的枚举类型头文件FirstEnum.h，如下图所示：</p>
<p id="EAOktLA"><img class="size-full wp-image-1882 aligncenter" src="/wp-content/uploads/2017/04/img_58eaf86e332c8.png" alt="" srcset="/wp-content/uploads/2017/04/img_58eaf86e332c8.png 524w, /wp-content/uploads/2017/04/img_58eaf86e332c8-300x155.png 300w" sizes="(max-width: 524px) 100vw, 524px" /></p>
<p>5. 点击类型信息浏览器右下方的“应用”按钮，这样会在“代码生成位置”中生成该枚举的定义（如果上面勾选了“生成代码”选项）及相关的“胶水”代码<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_9/cpp/behaviac_generated/types/internal/behaviac_customized_types.h">behaviac_customized_types.h</a>和<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_9/cpp/behaviac_generated/types/internal/behaviac_customized_types.cpp">behaviac_customized_types.cpp</a>等文件，如下代码所示：</p>
<pre>// behaviac_customized_types.h

// 如下枚举的定义代码，会根据是否勾选了上面所说的“生成代码”选项来决定是否生成

enum FirstEnum
{
    e1,
    e2,
    e3,
};

// 如下代码，不管是否勾选了“生成代码”选项，都会自动生成
 
DECLARE_BEHAVIAC_ENUM_EX(FirstEnum, FirstEnum);
BEHAVIAC_DECLARE_TYPE_VECTOR_HANDLER(FirstEnum);


// behaviac_customized_types.cpp

BEHAVIAC_BEGIN_ENUM_EX(FirstEnum, FirstEnum)
{
    BEHAVIAC_ENUMCLASS_DISPLAY_INFO_EX(L"FirstEnum", L"");

    BEHAVIAC_ENUM_ITEM_EX(e1, "e1");
    BEHAVIAC_ENUM_ITEM_EX(e2, "e2");
    BEHAVIAC_ENUM_ITEM_EX(e3, "e3");
}
BEHAVIAC_END_ENUM_EX()</pre>
<p id="CpEirBJ">6. 为FirstAgent类新增成员属性p1，其类型是枚举“FirstEnum”，如下图所示：</p>
<p id="CmrqJLa"><img class="size-full wp-image-1883 aligncenter" src="/wp-content/uploads/2017/04/img_58eaf9f4a4b79.png" alt="" srcset="/wp-content/uploads/2017/04/img_58eaf9f4a4b79.png 612w, /wp-content/uploads/2017/04/img_58eaf9f4a4b79-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>7. 点击类型信息浏览器右下方的“应用”按钮，将“代码生成位置”中<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_9/cpp/behaviac_generated/types/">behaviac_generated/types</a>目录下所有生成的代码文件，添加到自己的项目中一起编译构建。</p>
<p>8. 新增行为树“EnumBT”，并使用成员属性p1来赋值和做比较运算，如下图所示：</p>
<p id="LrmqVUt"><img class="aligncenter size-full wp-image-1884" src="/wp-content/uploads/2017/04/MSNFMW7Q6EURC2KZS_9B.png" alt="" width="823" height="292" srcset="/wp-content/uploads/2017/04/MSNFMW7Q6EURC2KZS_9B.png 823w, /wp-content/uploads/2017/04/MSNFMW7Q6EURC2KZS_9B-300x106.png 300w, /wp-content/uploads/2017/04/MSNFMW7Q6EURC2KZS_9B-768x272.png 768w" sizes="(max-width: 823px) 100vw, 823px" /></p>
<p>9. 执行该行为树，得到如下执行结果：<br />
<img class="aligncenter size-full wp-image-1887" src="/wp-content/uploads/2017/04/AJHJULEHE0FKBDAI7F.png" alt="" width="166" height="145" /></p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_9">tutorials/tutorial_9</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_9_extend_enum/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程10：定制自己的读取方式来加载行为树</title>
		<link>/tutorial_10_extent_filemanager/</link>
					<comments>/tutorial_10_extent_filemanager/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Thu, 13 Apr 2017 06:16:45 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1905</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 有的时候，由于自身项目的需要，例如对行为树文件进行加密、打包等处理，behavi<a class="moretag" href="/tutorial_10_extent_filemanager/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>有的时候，由于自身项目的需要，例如对行为树文件进行加密、打包等处理，behaviac组件默认提供的文件加载机制不再满足需要，因此程序端需要定制自己的读取方式来加载行为树文件。</p>
<h2>C++版</h2>
<p>1. 需要从behaviac::CFileManager派生出自己的子类，并根据需要重载相关的方法，如下代码所示：</p>
<pre>#include "behaviac/common/file/filemanager.h"

<strong>class BEHAVIAC_API MyFileManager : public behaviac::CFileManager</strong>
{
public:
    <strong>BEHAVIAC_DECLARE_MEMORY_OPERATORS(MyFileManager);</strong>

    MyFileManager();
    virtual ~MyFileManager();

    virtual behaviac::IFile* FileOpen(const char* fileName, behaviac::CFileSystem::EOpenMode iOpenAccess = behaviac::CFileSystem::EOpenMode_Read);

    virtual void FileClose(behaviac::IFile* file);
    virtual bool FileExists(const char* fileName);
    virtual bool FileExists(const behaviac::string&amp; filePath, const behaviac::string&amp; ext);

    virtual uint64_t FileGetSize(const char* fileName);
    virtual behaviac::wstring GetCurrentWorkingDirectory();
};</pre>
<p>2. 根据自己的开发平台需要，实现相应的方法，这里只是简单的调用了基类的同名方法，仅用于演示流程，如下代码所示：</p>
<pre>#include "myfilemanager.h"

MyFileManager::MyFileManager()
{
}

MyFileManager::~MyFileManager()
{
}

behaviac::IFile* MyFileManager::FileOpen(const char* fileName, behaviac::CFileSystem::EOpenMode iOpenAccess)
{
    // 需要实现自己的代码，这里直接调用基类的方法仅供演示
    return CFileManager::FileOpen(fileName, iOpenAccess);
}

void MyFileManager::FileClose(behaviac::IFile* file)
{
    CFileManager::FileClose(file);
}

bool MyFileManager::FileExists(const behaviac::string&amp; filePath, const behaviac::string&amp; ext)
{
    return CFileManager::FileExists(filePath, ext);
}

bool MyFileManager::FileExists(const char* fileName)
{
    return CFileManager::FileExists(fileName);
}

uint64_t MyFileManager::FileGetSize(const char* fileName)
{
    return CFileManager::FileGetSize(fileName);
}

behaviac::wstring MyFileManager::GetCurrentWorkingDirectory()
{
    return CFileManager::GetCurrentWorkingDirectory();
}</pre>
<p>3. 在程序端初始化的地方，创建MyFileManager实例，如下代码所示：</p>
<pre>bool InitBehavic()
{
    LOGI("InitBehavic\n");

    <strong>g_MyFileManager = BEHAVIAC_NEW MyFileManager();</strong>

    behaviac::Workspace::GetInstance()-&gt;SetFilePath("../tutorials/tutorial_10/cpp/exported");

    behaviac::Workspace::GetInstance()-&gt;SetFileFormat(behaviac::Workspace::EFF_xml);

    return true;
}</pre>
<p>4. 调用Agent::btload()方法，就可以通过上面实现的MyFileManager来加载行为树文件了（Agent::btload()方法内部会执行到MyFileManager::FileOpen()方法），如下代码所示：</p>
<pre>bool InitPlayer()
{
    LOGI("InitPlayer\n");

    g_FirstAgent = behaviac::Agent::Create&lt;FirstAgent&gt;();

    <strong>bool bRet = g_FirstAgent-&gt;btload("FirstBT");</strong>

    g_FirstAgent-&gt;btsetcurrent("FirstBT");

    return bRet;
}</pre>
<p>5. 在程序端结束清理的地方，销毁上面创建的MyFileManager实例，如下代码所示：</p>
<pre>void CleanupBehaviac()
{
    LOGI("CleanupBehaviac\n");

    behaviac::Workspace::GetInstance()-&gt;Cleanup();

    if (g_MyFileManager)
    {
        <strong>BEHAVIAC_DELETE(g_MyFileManager);</strong>
        g_MyFileManager = NULL;
    }
}</pre>
<h2>C#版</h2>
<p>1. 需要从behaviac.FileManager派生出自己的子类，并根据需要重载相关的方法，这里只是简单的调用了基类的同名方法，仅用于演示流程，如下代码所示：</p>
<pre><strong>public class MyFileManager : behaviac.FileManager</strong>
{
    public MyFileManager()
    {
    }

    public override byte[] FileOpen(string filePath, string ext)
    {
        // 需要实现自己的代码，这里直接调用基类的方法仅供演示
        return base.FileOpen(filePath, ext);
    }

    public override void FileClose(string filePath, string ext, byte[] fileHandle)
    {
        base.FileClose(filePath, ext, fileHandle);
    }
}</pre>
<p>2. 在程序端初始化的地方，创建MyFileManager实例，如下代码所示：</p>
<pre>static bool InitBehavic()
{
    Console.WriteLine("InitBehavic");

    <strong>g_MyFileManager = new MyFileManager();</strong>

    behaviac.Workspace.Instance.FilePath = "../../exported";
    behaviac.Workspace.Instance.FileFormat = behaviac.Workspace.EFileFormat.EFF_xml;

    return true;
}</pre>
<p>3. 调用Agent.btload()方法，就可以通过上面实现的MyFileManager来加载行为树文件了（Agent.btload()方法内部会执行到MyFileManager.FileOpen()方法），如下代码所示：</p>
<pre>static bool InitPlayer()
{
    Console.WriteLine("InitPlayer");

    g_FirstAgent = new FirstAgent();

    <strong>bool bRet = g_FirstAgent.btload("FirstBT");</strong>
    Debug.Assert(bRet);

    g_FirstAgent.btsetcurrent("FirstBT");

    return bRet;
}</pre>
<p>4. 在程序端结束清理的地方，释放上面创建的MyFileManager实例引用，如下代码所示：</p>
<pre>static void CleanupBehaviac()
{
    Console.WriteLine("CleanupBehaviac");

    behaviac.Workspace.Instance.Cleanup();

    <strong>g_MyFileManager = null;</strong>
}</pre>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_10">tutorials/tutorial_10</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_10_extent_filemanager/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程11：使用Android Studio编译构建behaviac</title>
		<link>/tutorial_11_android_studio/</link>
					<comments>/tutorial_11_android_studio/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Wed, 26 Apr 2017 03:47:20 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1982</guid>

					<description><![CDATA[Android Studio是一个为Android平台开发程序的集成开发环境，可供开发者免费使用。需要在官网下载并安装最新版的Android Studio，然后<a class="moretag" href="/tutorial_11_android_studio/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>Android Studio是一个为Android平台开发程序的集成开发环境，可供开发者免费使用。需要在<a href="https://developer.android.com/studio/index.html">官网</a>下载并安装最新版的Android Studio，然后继续后文的编译构建。</p>
<p>可以参考源码包中<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_11">tutorials/tutorial_11</a>的做法类似构建自己的项目，具体步骤如下：</p>
<p>1. 新建自己的项目。这里我们直接打开已有的<a href="https://github.com/Tencent/behaviac/blob/master/build/android_studio/behaviac_android">behaviac_android</a>项目，如下图所示：</p>
<p id="kdYtPSD"><img class="size-full wp-image-1990 aligncenter" src="/wp-content/uploads/2017/04/img_59001c9c9fb84.png" alt="" srcset="/wp-content/uploads/2017/04/img_59001c9c9fb84.png 495w, /wp-content/uploads/2017/04/img_59001c9c9fb84-300x292.png 300w" sizes="(max-width: 495px) 100vw, 495px" /></p>
<p>2. 双击打开<a href="https://github.com/Tencent/behaviac/blob/master/build/android_studio/behaviac_android/app/build.gradle">build.gradle</a>文件，如下图所示：</p>
<p><!--StartFragment --></p>
<p><img class="aligncenter size-full wp-image-1985" src="/wp-content/uploads/2017/04/U9ADKNKBJ1EPAX5WR11EM.png" alt="" width="583" height="390" srcset="/wp-content/uploads/2017/04/U9ADKNKBJ1EPAX5WR11EM.png 583w, /wp-content/uploads/2017/04/U9ADKNKBJ1EPAX5WR11EM-300x201.png 300w" sizes="(max-width: 583px) 100vw, 583px" /></p>
<p>3. 在打开的文件中，修改cmake文件的相对路径，如下代码所示：</p>
<div>
<pre>externalNativeBuild {
    cmake {
        path "../../../../CMakeLists.txt"
    }
}</pre>
</div>
<div>
<p>这是由于<a href="https://github.com/Tencent/behaviac/blob/master/CMakeLists.txt">CMakeLists.txt</a>所在的路径在源码包的最顶级，如下图所示：</p>
<p id="mvVbtJP"><img class="size-full wp-image-1986 aligncenter" src="/wp-content/uploads/2017/04/img_59000a14869f8.png" alt="" srcset="/wp-content/uploads/2017/04/img_59000a14869f8.png 228w, /wp-content/uploads/2017/04/img_59000a14869f8-153x300.png 153w" sizes="(max-width: 228px) 100vw, 228px" /></p>
<p>需要参考上面的CMakeLists.txt，用于编译构建behaviac组件。在这个CMakeLists.txt文件中，还需要添加自己的项目，这里是tutorial_11来做示范，如下代码所示：</p>
<pre>add_subdirectory ("${PROJECT_SOURCE_DIR}/tutorials/tutorial_11/cpp")</pre>
</div>
<div>
<p>4. 在tutorial_11项目中，也有自己的<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_11/cpp/CMakeLists.txt">CMakeLists.txt</a>，这个文件用于示范如何编译构建自己的项目，如下图所示：</p>
<p id="iWFpGqe"><img class="size-full wp-image-1987 aligncenter" src="/wp-content/uploads/2017/04/img_59000b40d531b.png" alt="" srcset="/wp-content/uploads/2017/04/img_59000b40d531b.png 330w, /wp-content/uploads/2017/04/img_59000b40d531b-300x192.png 300w" sizes="(max-width: 330px) 100vw, 330px" /></p>
</div>
<p>打开该文件，可以看到我们将tutorial_11作为一个lib来编译构建，如下代码所示：</p>
<pre>if (BEHAVIAC_ANDROID_STUDIO)
   add_library(tutorial_11 SHARED ${BTUNITTEST_INC} ${BTUNITTEST_SRC})
else()
   # add the executable
   add_executable(tutorial_11 ${BTUNITTEST_INC} ${BTUNITTEST_SRC})
endif()

target_link_libraries (tutorial_11 libbehaviac ${CMAKE_THREAD_LIBS_INIT})</pre>
<p>5. 新建Android所需的assets目录，将behaviac编辑器导出的行为树和类型信息文件全部放在该目录中，如下图所示：</p>
<p id="wnufpRg"><img class="size-full wp-image-2007 aligncenter" src="/wp-content/uploads/2017/04/img_5902c241c3fa0.png" alt="" /></p>
<p>6. 在<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_11/cpp/tutorial_11.cpp">tutorial_11.cpp</a>文件的InitBehavic()方法中，调用了Workspace::SetFilePath()接口，设置行为树加载路径，<strong>必须要以“assets:/”字符串开头</strong>，如下代码所示：</p>
<pre>const char* InitBehavic()
{
    LOGI("InitBehavic\n");

#if !BEHAVIAC_CCDEFINE_ANDROID
    behaviac::Workspace::GetInstance()-&gt;SetFilePath("../tutorials/tutorial_11/cpp/exported");
#else
<strong>    behaviac::Workspace::GetInstance()-&gt;SetFilePath("assets:/behaviac/exported");</strong>
#endif

    behaviac::Workspace::GetInstance()-&gt;SetFileFormat(behaviac::Workspace::EFF_xml);

    return "InitBehavic\n";
}</pre>
<p>7. 在项目的<a href="https://github.com/Tencent/behaviac/blob/master/build/android_studio/behaviac_android/app/src/main/java/com/tencent/behaviac/behaviac_android/MainActivity.java">MainActivity.java</a>文件中，加载behaviac_gcc_debug和tutorial_11_gcc_debug库，如下代码所示：</p>
<pre>static {
    System.loadLibrary("behaviac_gcc_debug");
    System.loadLibrary("tutorial_11_gcc_debug");
}</pre>
<p>8. 在onCreate()方法中调用C++的方法（这样处理仅供示范），并将AssetManager实例传递给C++端，如下代码所示：</p>
<pre>protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Example of a call to a native method
    TextView tv = (TextView) findViewById(R.id.sample_text);
    tv.setText(<strong>TestMain(getApplication().getAssets())</strong>);
}

public native String TestMain(android.content.res.AssetManager assetManager);</pre>
<p>9. 在<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_11/cpp/tutorial_11.cpp">tutorial_11.cpp</a>文件中，实现了上一步中的TestMain()方法，调用接口Workspace::SetAssetManager()设置AssetManager实例，如下代码所示：</p>
<pre>extern "C"
JNIEXPORT jstring JNICALL
Java_com_tencent_behaviac_behaviac_1android_MainActivity_TestMain(JNIEnv* env, jclass cls, jobject assetManager)
{
    AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
    BEHAVIAC_ASSERT(mgr);

    <strong>behaviac::CFileManager::GetInstance()-&gt;SetAssetManager(mgr);</strong>

    std::string str = <strong>TestBehaviac();</strong>

    return env-&gt;NewStringUTF(str.c_str());
}</pre>
<p>&nbsp;</p>
<p>10. 编译构建APK包，并安装运行，结果如下图所示：</p>
<p id="oWrYuZH"><img class="size-full wp-image-1992 aligncenter" src="/wp-content/uploads/2017/04/img_59001ddad05df.png" alt="" /></p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_11">tutorials/tutorial_11</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_11_android_studio/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程12：并行节点的使用</title>
		<link>/tutorial_12_parallel/</link>
					<comments>/tutorial_12_parallel/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Tue, 25 Apr 2017 04:04:20 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1939</guid>

					<description><![CDATA[本文档描述的是3.6.34及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 并行节点用于一般意义上并行的执行所有子节点，相关的功能和属性说明详见手册《<a class="moretag" href="/tutorial_12_parallel/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6.34及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>并行节点用于一般意义上并行的执行所有子节点，相关的功能和属性说明详见手册《<a href="/language/zh/parallel/">并行节点</a>》。</p>
<p>并行节点容易在其属性配置上产生误用，本文将结合行为树中对并行节点的实际使用来加以说明。</p>
<p>1. 首先创建Agent子类“FirstAgent”及其成员属性p1和成员方法Say(behaviac::string&amp; value, bool isLatent)，Say()方法用于打印指定的参数，如下图所示：</p>
<p id="AhQHURQ"><img class="size-full wp-image-2031 aligncenter" src="/wp-content/uploads/2017/05/img_5909a93aaff59.png" alt="" srcset="/wp-content/uploads/2017/05/img_5909a93aaff59.png 612w, /wp-content/uploads/2017/05/img_5909a93aaff59-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<p>Say()方法表示对于isLatent为真的情况，在第三帧后返回成功，前两帧返回正在执行；而对于isLatent为假的情况，在第一帧就直接返回成功，其实现代码如下所示：</p>
<pre>behaviac::EBTStatus FirstAgent::Say(behaviac::string&amp; value, bool isLatent)
{
///&lt;&lt;&lt; BEGIN WRITING YOUR CODE Say
    if (isLatent &amp;&amp; behaviac::Workspace::GetInstance()-&gt;GetFrameSinceStartup() &lt; 3)
    {
        printf("\n%s [Running]\n\n", value.c_str());

        return behaviac::BT_RUNNING;
    }

    printf("\n%s [Success]\n\n", value.c_str());

    return behaviac::BT_SUCCESS;
///&lt;&lt;&lt; END WRITING YOUR CODE
}</pre>
<p>其中，当前帧数在主循环代码中每帧进行累加，如下代码所示：</p>
<pre>void UpdateLoop()
{
    LOGI("UpdateLoop\n");

    behaviac::Workspace::GetInstance()-&gt;SetFrameSinceStartup(0);

    behaviac::EBTStatus status = behaviac::BT_RUNNING;

    while (status == behaviac::BT_RUNNING)
    {
        behaviac::Workspace::GetInstance()-&gt;SetFrameSinceStartup(behaviac::Workspace::GetInstance()-&gt;GetFrameSinceStartup() + 1);

        LOGI("frame %d\n", behaviac::Workspace::GetInstance()-&gt;GetFrameSinceStartup());

        status = g_FirstAgent-&gt;btexec();
    }
}</pre>
<p>2. 创建行为树“ParallelBT”，其中并行节点有3个子节点，第一个是条件节点，第二和三个都是动作节点，如下图所示：</p>
<p id="NJvyZLO"><img class="size-full wp-image-2045 aligncenter" src="/wp-content/uploads/2017/05/img_59194b03da0fb.png" alt="" srcset="/wp-content/uploads/2017/05/img_59194b03da0fb.png 1098w, /wp-content/uploads/2017/05/img_59194b03da0fb-300x95.png 300w, /wp-content/uploads/2017/05/img_59194b03da0fb-768x242.png 768w, /wp-content/uploads/2017/05/img_59194b03da0fb-1024x323.png 1024w" sizes="(max-width: 1098px) 100vw, 1098px" /></p>
<p>3. 该并行节点的的属性默认配置如下图所示：</p>
<p><img class="size-full wp-image-1943 aligncenter" src="/wp-content/uploads/2017/04/img_58feb9cd3d315.png" alt="" srcset="/wp-content/uploads/2017/04/img_58feb9cd3d315.png 475w, /wp-content/uploads/2017/04/img_58feb9cd3d315-300x105.png 300w" sizes="(max-width: 475px) 100vw, 475px" /></p>
<ul>
<li><strong>失败条件：</strong>FAIL_ON_ONE表示一个子节点返回失败，那么并行节点就返回失败。</li>
<li><strong>成功条件：</strong>SUCCEED_ON_ALL表示所有子节点都返回成功，并行节点才返回成功。这里需要注意，失败条件优先于成功条件。</li>
<li><strong>子节点结束继续条件：</strong>CHILDFINISH_LOOP表示子节点结束后会重新再循环执行。</li>
<li><strong>退出行为：</strong>EXIT_ABORT_RUNNINGSIBLINGS表示当并行节点的成功或失败条件满足并返回成功或失败后，会终止掉其他还在运行的子节点。</li>
</ul>
<p>4. 执行该行为树，结果如下图所示：</p>
<p id="WKjlFhz"><img class="size-full wp-image-2035 aligncenter" src="/wp-content/uploads/2017/05/img_5909ab958726a.png" alt="" srcset="/wp-content/uploads/2017/05/img_5909ab958726a.png 214w, /wp-content/uploads/2017/05/img_5909ab958726a-137x300.png 137w" sizes="(max-width: 214px) 100vw, 214px" /></p>
<p>5. 将并行节点的属性“子节点结束继续条件”改为CHILDFINISH_ONCE，表示子节点结束后不再执行（除非重入该并行节点），如下图所示：</p>
<p id="ksHGkoe"><img class="size-full wp-image-1948 aligncenter" src="/wp-content/uploads/2017/04/img_58fec8784ee36.png" alt="" srcset="/wp-content/uploads/2017/04/img_58fec8784ee36.png 477w, /wp-content/uploads/2017/04/img_58fec8784ee36-300x103.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>6. 再执行该行为树，结果如下图所示：</p>
<p id="yzOtmuW"><img class="size-full wp-image-2036 aligncenter" src="/wp-content/uploads/2017/05/img_5909ac085f1a6.png" alt="" srcset="/wp-content/uploads/2017/05/img_5909ac085f1a6.png 217w, /wp-content/uploads/2017/05/img_5909ac085f1a6-175x300.png 175w" sizes="(max-width: 217px) 100vw, 217px" /></p>
<p>从上图可以看到，虽然一共循环了3次，但ID为7的动作节点只执行了一次，而ID为0的动作节点由于前两帧执行时返回Running，得到持续执行，直到第三帧返回Success或Failure。</p>
<p>7. 将并行节点的属性“失败条件”改为FAIL_ON_ALL，并将“成功条件”改为SUCCEED_ON_ONE，如下图所示：</p>
<p id="ecycJfE"><img class="size-full wp-image-1949 aligncenter" src="/wp-content/uploads/2017/04/img_58fec9ec1afdb.png" alt="" srcset="/wp-content/uploads/2017/04/img_58fec9ec1afdb.png 477w, /wp-content/uploads/2017/04/img_58fec9ec1afdb-300x104.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>8. 再执行该行为树，结果如下图所示：</p>
<p id="ZDFiGAF"><img class="size-full wp-image-2046 aligncenter" src="/wp-content/uploads/2017/05/img_59194b7c8c160.png" alt="" /></p>
<p>从上图可以看到，一共循环了1次，并行节点的所有子节点也都执行了1次。</p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_12">tutorials/tutorial_12</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_12_parallel/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>教程13：随机与概率相关节点的使用</title>
		<link>/tutorial_13_random_nodes/</link>
					<comments>/tutorial_13_random_nodes/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Tue, 25 Apr 2017 11:19:30 +0000</pubDate>
				<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">/?p=1967</guid>

					<description><![CDATA[本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。 为了方便使用，behaviac组件除了提供传统的序列、选择等组合节点之外，还提供<a class="moretag" href="/tutorial_13_random_nodes/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<pre>本文档描述的是3.6及以后版本，对于3.5及以前的老版本请参考分类“3.5”。</pre>
<p>为了方便使用，behaviac组件除了提供传统的序列、选择等组合节点之外，还提供了随机与概率相关的节点类型，主要包括<a href="/language/zh/sequencestochastic/">随机序列（SequenceStochastic）</a>、<a href="/language/zh/selectorstochastic/">随机选择（SelectorStochastic）</a>和<a href="/language/zh/selectorprobability/">概率选择（SelectorProbability）</a>等节点。</p>
<p>这3个节点对于初学者容易混淆，本文将结合行为树中对这3个节点的使用来分别加以说明。</p>
<h2><span class="ez-toc-section" id="1">1. 创建类型信息</span></h2>
<p>首先创建Agent子类“FirstAgent”及其成员方法Say(behaviac::string&amp; value)，Say()方法用于打印指定的参数，如下图所示：</p>
<p id="cLqSFmy"><img class="size-full wp-image-1945 aligncenter" src="/wp-content/uploads/2017/04/img_58febc064178c.png" alt="" srcset="/wp-content/uploads/2017/04/img_58febc064178c.png 612w, /wp-content/uploads/2017/04/img_58febc064178c-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></p>
<h2><span class="ez-toc-section" id="2">2. 随机序列节点</span></h2>
<p>如果对随机序列节点不熟悉，请首先查看其手册《<a href="/language/zh/sequencestochastic/">随机序列节点</a>》。</p>
<p>1. 创建行为树“sequencestochasticBT”，其中随机序列节点有3个动作子节点，分别输出“A”、“B”、“C”，如下图所示：</p>
<p id="RdIyQom"><img class="size-full wp-image-1968 aligncenter" src="/wp-content/uploads/2017/04/img_58ff13286fbe7.png" alt="" srcset="/wp-content/uploads/2017/04/img_58ff13286fbe7.png 947w, /wp-content/uploads/2017/04/img_58ff13286fbe7-300x93.png 300w, /wp-content/uploads/2017/04/img_58ff13286fbe7-768x237.png 768w" sizes="(max-width: 947px) 100vw, 947px" /></p>
<p>2. 随机序列节点的的属性“随机数”默认为空，表示使用系统默认的随机数产生器，当然也可以配置自己实现的随机数方法，这里我们保持为空即可，如下图所示：</p>
<p id="hEtkPWQ"><img class="size-full wp-image-1969 aligncenter" src="/wp-content/uploads/2017/04/img_58ff13b8973e4.png" alt="" srcset="/wp-content/uploads/2017/04/img_58ff13b8973e4.png 478w, /wp-content/uploads/2017/04/img_58ff13b8973e4-300x63.png 300w" sizes="(max-width: 478px) 100vw, 478px" /></p>
<p>3. 执行该行为树，结果如下图所示：</p>
<p id="YbFitvC"><img class="size-full wp-image-1970 aligncenter" src="/wp-content/uploads/2017/04/img_58ff14c07f01c.png" alt="" /></p>
<p>可以看到随机输出了“B”、“C”、“A”，但多次执行程序，发现都是输出这个顺序，并没有随机输出。这是由于没有调用随机种子方法，需要在代码中调用如下接口即可：</p>
<pre>#if BEHAVIAC_CCDEFINE_MSVC
    time_t timer;
    time(&amp;timer);

    behaviac::RandomGenerator::GetInstance()-&gt;setSeed((unsigned int)timer);
#endif</pre>
<h2><span class="ez-toc-section" id="3">3. 随机选择节点</span></h2>
<p>如果对随机选择节点不熟悉，请首先查看其手册《<a href="/language/zh/selectorstochastic/">随机选择节点</a>》。</p>
<p>1. 创建行为树“selectorstochasticBT”，其中随机选择节点有3个动作子节点，分别输出“A”、“B”、“C”，如下图所示：</p>
<p id="lAjLUVo"><img class="size-full wp-image-1971 aligncenter" src="/wp-content/uploads/2017/04/img_58ff2f4c29fee.png" alt="" srcset="/wp-content/uploads/2017/04/img_58ff2f4c29fee.png 925w, /wp-content/uploads/2017/04/img_58ff2f4c29fee-300x91.png 300w, /wp-content/uploads/2017/04/img_58ff2f4c29fee-768x233.png 768w" sizes="(max-width: 925px) 100vw, 925px" /></p>
<p>2. 随机选择节点的的属性“随机数”默认为空，表示使用系统默认的随机数产生器，当然也可以配置自己实现的随机数方法，这里我们保持为空即可，如下图所示：</p>
<p id="wyjDAMd"><img class="size-full wp-image-1972 aligncenter" src="/wp-content/uploads/2017/04/img_58ff2f7896b99.png" alt="" srcset="/wp-content/uploads/2017/04/img_58ff2f7896b99.png 478w, /wp-content/uploads/2017/04/img_58ff2f7896b99-300x63.png 300w" sizes="(max-width: 478px) 100vw, 478px" /></p>
<p>3. 执行该行为树，结果如下图所示：</p>
<p id="pbDGEOZ"><img class="size-full wp-image-1973 aligncenter" src="/wp-content/uploads/2017/04/img_58ff2f9fbf1cc.png" alt="" /></p>
<p>可以看到随机输出了“C”，多次执行程序，可以看到还会随机输出“A”或“B”。</p>
<h2><span class="ez-toc-section" id="4">4. 概率选择节点</span></h2>
<p>如果对概率选择节点不熟悉，请首先查看其手册《<a href="/language/zh/selectorprobability/">概率选择节点</a>》。</p>
<p>1. 创建行为树“selectorprobabilityBT”，其中概率选择节点有3个动作子节点，权值分别为20、30、50，表示分别会已20%、30%、50%的概率输出“A”、“B”、“C”，如下图所示：</p>
<p id="zQrSEOb"><img class="size-full wp-image-1974 aligncenter" src="/wp-content/uploads/2017/04/img_58ff3033c6eaa.png" alt="" srcset="/wp-content/uploads/2017/04/img_58ff3033c6eaa.png 1096w, /wp-content/uploads/2017/04/img_58ff3033c6eaa-300x71.png 300w, /wp-content/uploads/2017/04/img_58ff3033c6eaa-768x183.png 768w, /wp-content/uploads/2017/04/img_58ff3033c6eaa-1024x244.png 1024w" sizes="(max-width: 1096px) 100vw, 1096px" /></p>
<p>2. 概率选择节点节点的的属性“随机数”默认为空，表示使用系统默认的随机数产生器，当然也可以配置自己实现的随机数方法，这里我们保持为空即可，如下图所示：</p>
<p id="UTBKQlv"><img class="size-full wp-image-1975 aligncenter" src="/wp-content/uploads/2017/04/img_58ff3059aac62.png" alt="" srcset="/wp-content/uploads/2017/04/img_58ff3059aac62.png 477w, /wp-content/uploads/2017/04/img_58ff3059aac62-300x59.png 300w" sizes="(max-width: 477px) 100vw, 477px" /></p>
<p>3. 执行该行为树，结果如下图所示：</p>
<p id="TUIXabU"><img class="size-full wp-image-1976 aligncenter" src="/wp-content/uploads/2017/04/img_58ff30a48dadb.png" alt="" /></p>
<p>可以看到随机输出了“B”，多次执行程序，可以看到还会随机输出“A”或“C”。</p>
<p>本教程相关的工作区和代码工程详见源码包的目录<a href="https://github.com/Tencent/behaviac/blob/master/tutorials/tutorial_13">tutorials/tutorial_13</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial_13_random_nodes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>目录结构</title>
		<link>/directory/</link>
					<comments>/directory/#respond</comments>
		
		<dc:creator><![CDATA[jonygli]]></dc:creator>
		<pubDate>Mon, 11 Apr 2016 09:58:37 +0000</pubDate>
				<category><![CDATA[文章]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[概述]]></category>
		<guid isPermaLink="false">/?p=162</guid>

					<description><![CDATA[首先说明的是从下载链接获取的BehaviacSetup*.exe是安装包，内含可执行的编辑器及示例。 如果编辑器不能正常启动，需要下载安装Microsoft V<a class="moretag" href="/directory/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>首先说明的是从<a href="/language/zh/downloads/">下载链接</a>获取的BehaviacSetup*.exe是安装包，内含可执行的编辑器及示例。</p>
<p>如果编辑器不能正常启动，需要下载安装<a href="https://support.microsoft.com/en-us/kb/2977003">Microsoft Visual C++ 运行库</a>及<a href="https://www.microsoft.com/en-US/download/details.aspx?id=21">.net框架</a>。</p>
<p>可以从<a href="/language/zh/downloads/">下载链接</a>下载或从<a href="https://github.com/Tencent/behaviac">github</a>克隆源码，这里介绍的是源码的目录结构。</p>
<h3 id="section">目录结构图示</h3>
<p><img class="aligncenter size-full wp-image-1411" src="/wp-content/uploads/2016/04/directory.png" alt="directory" width="177" height="346" srcset="/wp-content/uploads/2016/04/directory.png 177w, /wp-content/uploads/2016/04/directory-153x300.png 153w" sizes="(max-width: 177px) 100vw, 177px" /></p>
<h3 id="section-1">目录结构说明</h3>
<ul>
<li>build：构建脚本，使用CMake构建。可以参考文档<a href="/language/zh/how_to_build/">《如何编译构建》</a>。</li>
<li>docs：文档，目前只有behaviac.chm，以后访问文档需要访问<a href="/">API</a></li>
<li>inc：运行时库的C++头文件</li>
<li>integration：Unity平台的实现及示例
<ul>
<li>demo_running：一个简单demo</li>
<li>unity：unity的实现及unittest</li>
</ul>
</li>
<li>projects：C++项目文件，用于打开unit test和tutorials等项目。这里的项目文件是预提供的，仅支持vs及make。如果需要其他平台，可以参考build目录下的构建脚本。</li>
<li>src：运行时库的C++源码</li>
<li>test：测试，C++
<ul>
<li>btperformance：简单的性能测试</li>
<li>btremotetest,：简单的连调测试</li>
<li>btunittest：C++ unit test</li>
<li>demo_running：简单的测试，适合少量修改，体会<a href="/docs/zh/articles/concepts/">行为树的概念</a></li>
<li>usertest：简单的测试，适合少量修改，做出自己的测试</li>
</ul>
</li>
<li>tools：编辑器的C#源码
<ul>
<li>designer</li>
</ul>
</li>
<li>tutorials：教程相关的源码，配合<a href="/language/zh/category/docs/tutorial/">教程相关文档</a>使用，方便上手</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>/directory/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>序列节点</title>
		<link>/sequence/</link>
					<comments>/sequence/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Thu, 12 May 2016 10:08:31 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=222</guid>

					<description><![CDATA[Sequence 节点是 BT 中传统的组合节点之一。 该节点以给定的顺序依次执行其子节点，直到所有子节点成功返回，该节点也返回成功。只要其中某个子节点失败，那<a class="moretag" href="/sequence/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p><img src="/img/references/sequence.png" alt="sequence" /></p>
<p>Sequence 节点是 BT 中传统的组合节点之一。 该节点以给定的顺序依次执行其子节点，直到所有子节点成功返回，该节点也返回成功。只要其中某个子节点失败，那么该节点也失败。</p>
<p>Sequence 实现了与（&amp;&amp;）的功能。我们知道表达式 R=A&amp;&amp;B&amp;&amp;C&amp;&amp;D 执行的时候首先执行 A，如果 A 是 false 则返回 false，如果 A 是 true 则执行 B，如果 B 是 false 则返回 false，否则如果 B 是 true 则执行 C，如果 C 是 false 则返回 false，否则如果 C 是 true 则执行 D，并且返回D 的值。</p>
<p>最一般的意义上， Sequence 节点实现了一个序列。 实际上， Sequence 节点不仅可以管理‘动作’子节点，也可以管理‘条件’子节点。 如上图的应用中， 如果1和2号节点是条件节点的话，这两个条件节点实际上用作进入下面其他节点的 precondition，只有这两个条件是 true，下面的其他节点才有可能执行。</p>
<p>此外， Sequence 上还可以添加‘中断条件’作为终止执行的条件。上图中红框所示就是可选的‘中断条件’。该‘中断条件’在每处理下一个子节点的时候被检查，当为true时，则不再继续，返回失败（Failure）。</p>
<p>具体的执行逻辑可以查看 <a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/sequence.cpp">behaviortree/nodes/composites/sequence.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/sequence/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>关于新旧版本的说明</title>
		<link>/version_desc/</link>
					<comments>/version_desc/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Thu, 08 Dec 2016 09:55:13 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<guid isPermaLink="false">/?p=1219</guid>

					<description><![CDATA[归类到“3.5”中的这些文章都是基于3.5及之前旧版本的文档，其他目录（“文章”、“教程”、“手册”等）下的文档都用于3.6及以上新版本，如下图所示： 其中，3<a class="moretag" href="/version_desc/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>归类到“3.5”中的这些文章都是基于3.5及之前旧版本的文档，其他目录（“文章”、“教程”、“手册”等）下的文档都用于3.6及以上新版本，如下图所示：</p>
<p><img src="/wp-content/uploads/2016/12/docs_menu.png" alt="" width="205" height="283" class="aligncenter size-full wp-image-1460" /></p>
<p>其中，3.6及以上新版本的主要特性如下所示：</p>
<p align="center"><video src="http://dlied5.qq.com/behaviac/behaviac_overview.mp4" controls="controls" width="480" height="288"><br />
您的浏览器不支持 video 标签。<br />
</video></p>
<p>behaviac在3.6之后的新版本，不再从运行时（程序端）导出类型信息，而是将类型信息的编辑工作全部放在了编辑器端，如下图所示：</p>
<p><img class="size-full wp-image-1261 aligncenter" src="/wp-content/uploads/2016/12/workflow-1.png" alt="workflow" width="590" height="279" srcset="/wp-content/uploads/2016/12/workflow-1.png 590w, /wp-content/uploads/2016/12/workflow-1-300x142.png 300w" sizes="(max-width: 590px) 100vw, 590px" /></p>
<p>新的设计是工作流从编辑器到运行时的单向箭头，也即类型信息完全在编辑器端设计，类型信息以源码的形式生成，程序端再把编辑器生成的类型信息相关的源码编译进程序。最后，程序端加载并执行编辑器导出的行为树。</p>
<p>整个设计有如下优点：</p>
<ul>
<li>流程简单，没有歧义</li>
<li>程序员不需要写任何额外的代码，只需要把生成的代码加入工程</li>
<li>支持方便的添加新的类型或属性、方法，修改已有的类型或属性、方法，不再需要多次修改</li>
<li>属性不再必须是public的，被有效的封装</li>
<li>数据的兼容性检测，尽力支持策划和程序员并行工作，尽力避免策划等待程序员更新</li>
<li>支持热更新，将允许在代码不改变的情况下使用自定义变量以及修改行为树</li>
</ul>
<h2><span class="ez-toc-section" id="i"><strong>工作区</strong></span></h2>
<p>工作区用于管理整个项目的配置，包括一些位置和语言等参数，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1175" src="/wp-content/uploads/2016/12/new_workspace.png" alt="new_workspace" width="587" height="272" srcset="/wp-content/uploads/2016/12/new_workspace.png 587w, /wp-content/uploads/2016/12/new_workspace-300x139.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<ul>
<li style="text-align: left;"><strong>工作区位置：</strong>保存工作区文件的目录，在该目录下会保存出*.workspace.xml的文件，该文件即是编辑器打开的工作区文件（或者称之为项目文件）。</li>
<li><strong>行为树源位置：</strong>对既有服务器，又有客户端的项目开发，可能需要共用行为树，这时候只要为服务器和客户端分别创建工作区，然后为它们设置相同的“行为树源位置”即可。这样，只需要编辑同一份行为树，就可以让服务器和客户端的AI逻辑保持一致。</li>
<li><strong>行为树导出位置：</strong>在该目录下，导出编辑好的行为树，并且需要在程序端设置的加载位置，以便程序运行起来后，加载所需的行为树。</li>
<li><strong>代码生成位置：</strong>用于存放后面将要描述的类型信息浏览器中编辑好的类型代码文件，还包含了一些“胶水”代码文件，都需要整合到运行时（游戏端）一起编译构建。</li>
<li><strong>程序端开发语言：</strong>可选cpp（即C++）和cs（即C#）两种，表示程序端的代码语言。结合上面所说的情况，可以支持服务器和客户端采用不同的语言编写代码，但共用同一份行为树数据。</li>
</ul>
<h2><span class="ez-toc-section" id="i-2">类型信息</span></h2>
<p>类型信息浏览器是进行类型信息查看和编辑的重要工具，可以管理（添加、删除、修改等）整个工作区所需的类型及其属性、方法、实例等信息，如下图所示：</p>
<h4><img class="aligncenter size-full wp-image-1264" src="/wp-content/uploads/2016/12/meta_browser-1.png" alt="meta_browser" width="612" height="735" srcset="/wp-content/uploads/2016/12/meta_browser-1.png 612w, /wp-content/uploads/2016/12/meta_browser-1-250x300.png 250w" sizes="(max-width: 612px) 100vw, 612px" /></h4>
<p style="text-align: left;">点击类型信息浏览器下方的“应用”按钮，编辑出来的类型信息会保存在工作区文件所在的同目录下。例如，假设工作区文件是FirstWorkspace.workspace.xml，则在它所在的目录下，会自动保存出FirstWorkspace.meta.xml文件。</p>
<p style="text-align: left;">此外，点击“应用”按钮后，还会在工作区中设置的“代码生成位置”生成类型及其相关的“胶水”代码文件。点击左下方的“打开代码生成位置”按钮，弹出“behaviac_generated/types”目录，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1184" src="/wp-content/uploads/2016/12/export_path.png" alt="export_path" width="310" height="186" srcset="/wp-content/uploads/2016/12/export_path.png 310w, /wp-content/uploads/2016/12/export_path-300x180.png 300w" sizes="(max-width: 310px) 100vw, 310px" /></p>
<p>注意：在自己的项目中，需要将“behaviac_generated/types/internal”目录中的所有cpp文件添加进自己的项目中，并且将“behaviac_types.h”头文件包含到自己的代码中以便能使用这些自动生成的“胶水”代码，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1222" src="/wp-content/uploads/2016/12/include_project.png" alt="include_project" width="286" height="208" /></p>
<p>其中，“behaviac_generated/types/internal”目录中的behaviac_agent_member_visitor.h文件生成了用于访问类的私有属性和方法的“胶水”代码，behaviac_agent_meta.h/cpp文件生成了用于注册类及其属性、方法、实例等信息的“胶水”代码，这些“胶水”代码的作用是为了程序端运行时，可以通过名字自动取用到类及其成员属性、方法及其实例等。</p>
<p>FirstAgent.h/cpp是生成的Agent子类文件，在里面可以根据需要继续添加自己的代码，如下代码所示：</p>
<p>FirstAgent.h：</p>
<pre style="padding-left: 30px;">#ifndef _BEHAVIAC_FIRSTAGENT_H_
#define _BEHAVIAC_FIRSTAGENT_H_

#include "behaviac_agent_headers.h"

///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FILE_INIT

///&lt;&lt;&lt; END WRITING YOUR CODE

class FirstAgent : public behaviac::Agent
    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FirstAgent
    ///&lt;&lt;&lt; END WRITING YOUR CODE
{
public:
    FirstAgent();

    virtual ~FirstAgent();

    BEHAVIAC_DECLARE_AGENTTYPE(FirstAgent, behaviac::Agent)

private:
    int p1;
public:
    inline void _set_p1(int value)
    {
        p1 = value;
    }
    inline int&amp; _get_p1()
    {
        return p1;
    }

public:
    void m1();

    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE CLASS_PART

    ///&lt;&lt;&lt; END WRITING YOUR CODE
};

///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FILE_UNINIT

///&lt;&lt;&lt; END WRITING YOUR CODE

#endif</pre>
<p>FirstAgent.cpp：</p>
<pre>#include "FirstAgent.h"

///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FILE_INIT

///&lt;&lt;&lt; END WRITING YOUR CODE

FirstAgent::FirstAgent()
{
    p1 = 0;

    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE CONSTRUCTOR

    ///&lt;&lt;&lt; END WRITING YOUR CODE
}

FirstAgent::~FirstAgent()
{
    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE DESTRUCTOR

    ///&lt;&lt;&lt; END WRITING YOUR CODE
}

void FirstAgent::m1()
{
    ///&lt;&lt;&lt; BEGIN WRITING YOUR CODE m1

    ///&lt;&lt;&lt; END WRITING YOUR CODE
}

///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FILE_UNINIT

///&lt;&lt;&lt; END WRITING YOUR CODE</pre>
<p>注意：自己的代码需要添加在“///&lt;&lt;&lt; BEGIN WRITING YOUR CODE FILE_INIT”和“///&lt;&lt;&lt; END WRITING YOUR CODE”之间，以便下次生成代码时，可以自动进行合并。</p>
<p>此外，如果该类并没有勾选“生成代码”选项，那么在点击“应用”按钮后，将不会生成该类的代码，需要你自己完全手工编写。为了提高手工编写代码的效率，可以点击类型信息浏览器右上方的“预览原型代码”按钮，将会弹出该类的原型代码，可以选择需要的内容复制到你的代码中，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1186" src="/wp-content/uploads/2016/12/preview_prototype.png" alt="preview_prototype" width="605" height="230" srcset="/wp-content/uploads/2016/12/preview_prototype.png 605w, /wp-content/uploads/2016/12/preview_prototype-300x114.png 300w, /wp-content/uploads/2016/12/preview_prototype-604x230.png 604w" sizes="(max-width: 605px) 100vw, 605px" /></p>
<p style="text-align: left;">如果生成的文件中需要引用到你的项目中的其他头文件，可以点击上图中的“设置头文件”按钮，添加自己需要的.h文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1187" src="/wp-content/uploads/2016/12/set_headers.png" alt="set_headers" width="524" height="271" srcset="/wp-content/uploads/2016/12/set_headers.png 524w, /wp-content/uploads/2016/12/set_headers-300x155.png 300w" sizes="(max-width: 524px) 100vw, 524px" /></p>
<h2 style="text-align: left;"><span class="ez-toc-section" id="i-3"><strong>编辑行为树</strong></span></h2>
<p>根据在类型信息浏览器中创建的Agent子类，我们就可以开始创建和编辑行为树了。例如，行为树的根节点需要配置Agent类型，叶子节点需要配置相应的属性和方法，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1203" src="/wp-content/uploads/2016/12/right_bt.png" alt="right_bt" width="817" height="280" srcset="/wp-content/uploads/2016/12/right_bt.png 817w, /wp-content/uploads/2016/12/right_bt-300x103.png 300w, /wp-content/uploads/2016/12/right_bt-768x263.png 768w" sizes="(max-width: 817px) 100vw, 817px" /></p>
<p>在编辑器中编辑的行为树称之为”源行为树“，但程序端只能加载并执行导出后的行为树。因此，编辑完行为树之后，需要统一导出。</p>
<h2><span class="ez-toc-section" id="i-4"><strong>导出行为树</strong></span></h2>
<p>打开“导出”窗口，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1238" src="/wp-content/uploads/2016/12/export-1.png" alt="export" width="395" height="595" srcset="/wp-content/uploads/2016/12/export-1.png 395w, /wp-content/uploads/2016/12/export-1-199x300.png 199w" sizes="(max-width: 395px) 100vw, 395px" /></p>
<p style="text-align: left;">直接点击上图下方的 “导出”按钮，可以看到在工作区配置的“行为树导出位置”目录下，有了所有导出的行为树文件，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1223" src="/wp-content/uploads/2016/12/export_files-1.png" alt="export_files" width="226" height="191" /></p>
<h2 style="text-align: left;"><span class="ez-toc-section" id="i-5">使用行为树</span></h2>
<p style="text-align: left;">在程序端，需要指定上面提及的导出目录和文件格式，以便程序运行时能正常加载这些导出后的行为树，如下代码所示：</p>
<pre>behaviac::Workspace::GetInstance()-&gt;SetFilePath("../tutorials/tutorial_0/cpp/exported");

behaviac::Workspace::GetInstance()-&gt;SetFileFormat(behaviac::Workspace::EFF_xml);
</pre>
<p>然后，调用相应的加载接口，就可以加载所需的行为树了，如下代码所示：</p>
<pre>FirstAgent* g_FirstAgent = behaviac::Agent::Create&lt;FirstAgent&gt;();

g_FirstAgent-&gt;btload("FirstBT");

g_FirstAgent-&gt;btsetcurrent("FirstBT");</pre>
<p>加载完行为树，Agent实例就可以执行设置的当前行为树了，如下代码所示：</p>
<pre>g_FirstAgent-&gt;btexec();</pre>
<p>此外，在“行为树导出位置”目录下的meta文件夹包含了*.meta.xml文件，该文件内含有Agent子类的自定义属性，可以用来做Agent子类新增（自定义）成员属性的热更新。</p>
]]></content:encoded>
					
					<wfw:commentRss>/version_desc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>编辑器的安装</title>
		<link>/tutorial1_install/</link>
					<comments>/tutorial1_install/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:17:21 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[安装]]></category>
		<category><![CDATA[编辑器]]></category>
		<guid isPermaLink="false">/?p=267</guid>

					<description><![CDATA[首先从下载页面下载编辑器 可以查看目录结构 安装 安装behaviac套件的系统配置需求如下所示： 最低配置： 硬件环境： CPU：Intel core2 Du<a class="moretag" href="/tutorial1_install/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p><a href="/language/zh/behaviac%E7%89%88%E6%9C%AC%E4%B8%8B%E8%BD%BD/">首先从下载页面下载编辑器</a></p>
<p><a href="/language/zh/directory/">可以查看目录结构</a></p>
<h2 id="section">安装</h2>
<p>安装behaviac套件的系统配置需求如下所示：</p>
<h3 id="section-1">最低配置：</h3>
<p>硬件环境：</p>
<p>CPU：Intel core2 Duo 2.0G或同等配置</p>
<p>内存：2GB以上</p>
<p>显卡：nvidia 6600GT或同等配置</p>
<p>软件环境：</p>
<p>操作系统：Windows XP/Vista/7/8</p>
<p>屏幕分辨率：1024*768</p>
<h3 id="section-2">推荐配置：</h3>
<p>硬件环境：</p>
<p>CPU：Intel I5 2.93G或更高配置</p>
<p>内存：4GB以上</p>
<p>显卡：nvidia GTS450或更高配置</p>
<p>软件环境：</p>
<p>操作系统：Windows 7/8</p>
<p>屏幕分辨率：1680*1050</p>
<p>运行BehaviacSetup_***.exe安装包文件，选择安装路径（推荐直接使用默认路径），安装behaviac相关套件。</p>
<p>可能需要下载安装<a href="https://support.microsoft.com/en-us/kb/2977003">Microsoft Visual C++ 运行库</a>。<br />
及<a href="https://www.microsoft.com/en-US/download/details.aspx?id=21">.net</a>。</p>
<p>安装完成后，会在桌面生成编辑器的快捷方式，如下图所示：</p>
<p><img src="/img/tutorials/tutorial1/designerIcon.png" alt="" /></p>
<p>图1 安装后桌面的编辑器图标</p>
<p>另外，在系统的“开始”菜单中生成了一些游戏demo和文档的菜单项。其中，BattleCityDemo是采用Unity引擎实现的小游戏（C#版），LaunchCocosGame是采用Cocos引擎实现的小游戏（C++版），LaunchSDLDemo是采用SDL库实现的小游戏（C++版），如下图所示：</p>
<p><img src="/img/tutorials/tutorial1/startmenu.png" alt="" /></p>
<p>图2 开始菜单中demo和文档菜单项</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial1_install/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>编辑器的使用</title>
		<link>/tutorial2_usage/</link>
					<comments>/tutorial2_usage/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:18:49 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[编辑器]]></category>
		<guid isPermaLink="false">/?p=269</guid>

					<description><![CDATA[1 概述 behaviac中间件是我们对行为树、有限状态机等AI范式的一种整合实现方案，主要包括编辑器（Designer）和运行时库（Runtime）两大部分。<a class="moretag" href="/tutorial2_usage/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<h2 id="section"><span class="ez-toc-section" id="1">1 概述</span></h2>
<p>behaviac中间件是我们对行为树、有限状态机等AI范式的一种整合实现方案，主要包括编辑器（Designer）和运行时库（Runtime）两大部分。其中，编辑器用于编辑、导出类型信息，也用于编辑、导出和调试行为树；运行时库也可导出类型信息，主要用于解释和执行编辑器导出的行为树，运行时库需要整合到自己的游戏项目中去。</p>
<p>编辑器和运行时之间通过类型信息（Meta）进行交互，注意类型信息流动的双向箭头，表示编辑器和运行时库双方都可以导出类型信息，如下图所示：</p>
<p><img src="/img/overview/meta.png" alt="" /></p>
<p>图1 基于类型信息的编辑器和运行时端的交互</p>
<p>编辑器只能运行在Windows平台上，运行时库支持C++和C#语言两个版本，对Unity引擎原生支持C#，运行时库目前支持所有主流平台，包括Windows/Linux/Android/iOS等。</p>
<p>该组件的使用场景，支持但不限于游戏中的逻辑、角色的人工智能、动画的控制等方面。</p>
<h2 id="section-1"><span class="ez-toc-section" id="2">2 编辑器的使用</span></h2>
<h3 id="section-2"><span class="ez-toc-section" id="21">2.1 基本介绍</span></h3>
<p>编辑器首次打开后为会根据操作系统的语言环境配置自动设置为中文版或英文版的界面，若需更改语言显示，可以依次选择菜单项“文件（File）”-&gt;“设置（Settings）”，在弹出的设置对话框中，选择需要的“语言（Language）”并点击“确认（OK）”后，退出并重新打开编辑器，则转为需要语言的界面。<br />
编辑器主要分为几个部分：菜单和工具栏、行为树文件区、节点区、主视口和属性表等，如下图所示：</p>
<p><img src="/img/tutorials/tutorial2/designerMainWindow.png" alt="" /></p>
<p>图2.1 编辑器主界面</p>
<ul>
<li>菜单和工具栏：主要有新建/打开工作区、新建/保存/导出/关闭行为树文件、设置、退出、帮助等菜单项或按键。</li>
<li>行为树文件区：列出了当前打开的工作区里面的所有行为树文件，双击某个行为树文件节点可以打开该文件。</li>
<li>节点区：给出了behaviac组件支持的所有行为树节点类型，在编辑行为树的时候，可以通过鼠标拖拽添加到主视口的行为树上去。</li>
<li>主视口：显示了当前打开的行为树图形，可以打开多个行为树，分页显示。</li>
<li>属性表：在主视口中点击选择某个节点后，属性表会更新显示当前选中节点的所有属性，可以编辑各个属性。</li>
</ul>
<p>所有窗口的停靠位置均可根据个人喜好，通过鼠标在窗口边框的拖拽重新布局。编辑器中所有的按钮均可将鼠标停在上面查看其tips，以便查知其功能。编辑器中鼠标、键盘的按键用法介绍，请查看菜单中的“帮助（Help）”-&gt;“起始页（StartPage）”。</p>
<p>编辑器分为三种操作模式：<br />
&#8211; 编辑模式：这是常规模式，编辑器启动后默认进入该模式，主要用于为游戏项目编辑所需的类型信息和行为树。<br />
&#8211; 连接模式：这是编辑器连接上游戏之后进入的模式，此时不能编辑行为树本身，只能用于观察行为树的高亮执行路径、设置断点等调试相关的操作。<br />
&#8211; 分析模式：这是离线模式，在断开游戏时保存了连接过程中的所有消息，在该模式可以模拟连接模式游戏端发送过来的消息，进行离线分析行为树的执行情况。</p>
<h3 id="section-3"><span class="ez-toc-section" id="22">2.2 操作说明</span></h3>
<h4 id="section-4"><span class="ez-toc-section" id="221">2.2.1 新建工作区</span></h4>
<p>首次使用编辑器，需要为自己的项目创建一个工作区：</p>
<ul>
<li>点击菜单“文件”-&gt;“新建工作区”，弹出新建工作区对话框，如下图所示。</li>
</ul>
<p><img src="/img/tutorials/tutorial2/newWorkspace.png" alt="" /></p>
<p>图2.2.1 新建工作区</p>
<ul>
<li>依次设置工作区的名字、位置（即工作区的保存路径）、源位置（即原始行为树的保存路径）、导出位置（即运行时库所需行为树的导出路径）和元数据位置（即运行时库导出的类型信息文件路径）。</li>
<li>源位置是存放编辑器创建的行为树的位置。导出位置是存放导出的行为树的位置。源位置和导出位置缺省情况下位于工作区所在的目录内：behaviors和exported。</li>
<li>元数据位置、源位置和导出位置需要和工作区文件必须位于同一个盘符下（如果位于不同的盘符下，调试的时候会有问题）。缺省情况下，它们位于同一个顶级目录下。</li>
</ul>
<h4 id="section-5"><span class="ez-toc-section" id="222">2.2.2 打开工作区</span></h4>
<p>点击菜单“文件”-&gt;“打开工作区”，选择保存在磁盘上的*.workspace.xml文件。<br />
在安装路径下有提供的例子供参考，例如默认安装路径下的“C:\Program Files (x86)\behaviac\integration\BattleCityDemo\Assets\BTWorkspace\BattleCity.workspace.xml”，或者从菜单中的“文件”-&gt;“最近打开的工作区”列表中选择最近打开过的工作区。<br />
behaviac组件提供了C++和C#两种编程语言的单元测试以及游戏Demo，可以通过编辑器中的菜单项“帮助”-&gt;“控制说明” 进入，然后点击快速打开所需的单元测试或游戏Demo所用到的工作区，如下图所示：</p>
<p><img src="/img/tutorials/tutorial2/demoUnittest.png" alt="" /></p>
<p>图2.2.2 快速打开单元测试和游戏Demo的工作区</p>
<h4 id="section-6"><span class="ez-toc-section" id="223">2.2.3 编辑工作区</span></h4>
<p>点击菜单“文件”-&gt;“编辑工作区”，可以修改该工作区的设置（名字、元数据位置、源位置、导出位置等），如下图所示：</p>
<p><img src="/img/tutorials/tutorial2/editWorkspace.png" alt="" /></p>
<p>图2.2.3 编辑工作区</p>
<h4 id="section-7"><span class="ez-toc-section" id="224">2.2.4 新建并编辑行为树文件</span></h4>
<ul>
<li>在打开的工作区中，从工具栏里面点击“新建行为树”按钮或者通过菜单中“文件”-&gt;“新建行为树”项，创建一个行为树文件。</li>
<li>在主视口中，为新建的行为树根节点选择设置其“Agent类型”。</li>
<li>在“节点区”中用鼠标左键选择并拖拽一些节点到主视口中来构建需要的行为树，并设置每个节点的属性。每种节点的具体用法请参考菜单项“帮助”-&gt;“节点介绍”。</li>
<li>编辑过程中，支持Undo/Redo、保存等文件操作，鼠标、键盘的按键用法请对照菜单项“帮助”-&gt;“控制说明”。</li>
</ul>
<h4 id="section-8"><span class="ez-toc-section" id="225">2.2.5 打开行为树文件</span></h4>
<p>如图2.1所示，在“行为树文件区”中，双击某个行为树文件节点就可以在主视口中打开该文件。</p>
<h4 id="section-9"><span class="ez-toc-section" id="226">2.2.6 导出行为树文件</span></h4>
<ul>
<li>编辑完行为树之后，可以通过菜单项“文件”-&gt;“导出行为树”（或者快捷键Ctrl+T）导出当前打开的行为树文件。</li>
<li>通过菜单项“文件”-&gt;“导出全部”项（或者快捷键Ctrl+Shift+T）导出工作区中的所有行为树文件。</li>
<li>目前支持4种文件格式的导出，即XML、BSON、C++和C#，如下图所示：</li>
</ul>
<p><img src="/img/tutorials/tutorial2/exportBehaviors.png" alt="" /></p>
<p>图2.2.6.1 导出行为树</p>
<ul>
<li>对于C++/C#格式的导出，还可以设置导出的文件名和位置。点击图2.2.6.1中“导出设置”-&gt;“设置”列的“…”按钮，可以弹出“C++/C#导出设置”对话框。对于C++文件，还需添加游戏项目中Agent子类的.h头文件，如图2.2.6.2所示。<br />
导出后，将在指定的导出路径下生成behaviac_generated目录，里面又包含了behaviors和types两个子目录，需要将这两个子目录里面的所有文件全部包含到自己的项目中去。<br />
注意：对于导出C++文件，如果不添加Agent子类的.h头文件，那么需要注意将behaviors和types两个子目录中生成的头文件放在项目代码include “yourAgent.h”之后，以确保Agent子类先被包含进来，否则会有编译错误。</li>
</ul>
<p><img src="/img/tutorials/tutorial2/exportSettings.png" alt="" /></p>
<p>图2.2.6.2 C++/C#的导出设置</p>
<ul>
<li>图2.2.6.2中的选项“是否导出统一文件”用来表示导出的C++或者C#文件是否为一个统一的大文件还是若干个小文件，其中每个小文件对应一个行为树。</li>
<li>运行时库支持行为树导出文件的热加载，如果在编辑器修改完行为树之后，重新导出，游戏端会自动重新加载所用到的行为树，无需重启游戏。</li>
</ul>
<h4 id="section-10"><span class="ez-toc-section" id="227_Permalink">2.2.7 连接游戏<a class="header-link" title="Permalink" href="/docs/zh/tutorials/tutorial2_usage/#section-10"><span class="sr-only">Permalink</span><i class="fa fa-link"></i></a></span></h4>
<ul>
<li>从开始菜单中，启动小游戏BattleCityDemo，如下图所示：</li>
</ul>
<p><img src="/img/tutorials/tutorial2/battleCityDemo.png" alt="" /></p>
<p>图2.2.7.1 Battle City Demo</p>
<ul>
<li>点击游戏主界面右上角的“Show Levels”按钮，可以切换不同的关卡，如下图所示：</li>
</ul>
<p><img src="/img/tutorials/tutorial2/selectGameLevel.png" alt="" /></p>
<p>图2.2.7.2 选择关卡</p>
<ul>
<li>点击游戏主界面左下角的“Launch Designer”按钮，启动编辑器，编辑器会自动打开BattleCityDemo的工作区，并打开游戏当前关卡所用到的行为树（如果没有切换其他关卡，默认打开的是Tank_Fire_Random行为树文件）。</li>
<li>点击编辑器工具栏中的“连接游戏”按钮或通过菜单项“文件”-&gt;“连接游戏”（或通过快捷键Ctrl+L），开始连接游戏。默认的，一般无需更改服务器IP和端口号，如图2.2.7.3所示。<br />
注意：有时候可能会发现连不上游戏，很可能是原来的端口号已被占用，可以尝试在运行时端的端口号60636改为其他值，然后相应的修改图2.2.7.3中的端口号，尝试重新连接游戏。</li>
</ul>
<p><img src="/img/tutorials/tutorial2/connectGame.png" alt="" /></p>
<p>图2.2.7.3 连接游戏</p>
<ul>
<li>连接成功后，编辑器从编辑模式切换到连接模式，如下图所示：</li>
</ul>
<p><img src="/img/tutorials/tutorial2/connectMode.png" alt="" /></p>
<p>图2.2.7.4 连接模式</p>
<ul>
<li>时间轴（Timeline）：默认位于编辑器最上方，用于表示当前帧相关的信息。</li>
<li>实例列表：列出了游戏中所有的对象实例，双击实例节点后可以开始跟踪调试选中的实例，右键单击实例节点弹出如下菜单，如图2.2.7.5所示。其中“调试”跟双击节点的作用一致，开始跟踪选中的实例，主视口会高亮显示行为树的执行路径；“查看属性”用于跟踪当前选中实例的所有属性的变化，编辑器会弹出实例的属性列表。</li>
</ul>
<p><img src="/img/tutorials/tutorial2/debugInstance.png" alt="" /></p>
<p>图2.2.7.5 实例右键菜单</p>
<ul>
<li>主视口：高亮的节点边框和连接线段，表示程序当前执行的路径情况。双击树中节点的左右两侧，可以设置节点的断点（左侧表示进入断点，右侧表示退出断点），用于游戏执行时在断点位置停下来，游戏断下来后按F5键后继续运行。</li>
<li>输出窗口：列出了收到的全部消息，用于调试时查看记录。</li>
<li>Agent的属性：可以显示当前Agent属性的变化。</li>
<li>断点：通过菜单项“视图”-&gt;“断点”打开断点窗口后，可以查看、管理当前工作区中的所有断点。</li>
</ul>
<h4 id="section-11"><span class="ez-toc-section" id="228">2.2.8 分析导出数据</span></h4>
<ul>
<li>点击菜单或工具栏中的“断开游戏”按键，断开与游戏端的连接，回到编辑模式。</li>
<li>默认弹出如下对话框，保存之前连接模式下调试的相关数据。</li>
</ul>
<p><img src="/img/tutorials/tutorial2/saveDump.png" alt="" /></p>
<p>图2.2.8.1 保存dump数据</p>
<ul>
<li>点击菜单或工具栏中的“分析导出文件”按键，选择打开上一步导出的数据文件，编辑器进入到分析模式。</li>
<li>分析模式的界面布局跟连接模式类似，但是可以通过时间轴里面的播放按钮开始重现连接过程中的情况，如下图所示：</li>
</ul>
<p><img src="/img/tutorials/tutorial2/analyzeDump.png" alt="" /></p>
<p>图2.2.8.2 分析dump数据</p>
<ul>
<li>要退出分析模式，可以点击菜单或工具栏中的“终止分析”按键，回到编辑模式。</li>
</ul>
<p>需要指出的是，分析模式下还可以直接下载_behaviac_$_.log文件进行离线分析。_behaviac_$_.log文件一般生成在exe所在的目录。对于unity，_behaviac_$_.log文件生成在Assets所在的目录中。</p>
<h4 id="section-12"><span class="ez-toc-section" id="229">2.2.9 其他</span></h4>
<p>除了BattleCityDemo小游戏（基于Unity引擎实现，运行时库为C#版）之外，还有LaunchCocosGame（基于Cocos引擎实现，运行时库为C++版）和LaunchSDLDemo小游戏（基于SDL库实现，运行时库为C++版）。<br />
如图2.2所示，从操作系统的开始菜单中启动LaunchCocosGame或LaunchSDLDemo小游戏后，游戏跟编辑器的连接需要单独启动编辑器，然后再点击编辑器工具栏中的“连接游戏”按钮或通过菜单项“文件”-&gt;“连接游戏”（快捷键Ctrl+L），开始连接游戏。连接后，执行情况跟BattleCityDemo小游戏类似。</p>
<div class="section-nav"></div>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial2_usage/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>如何编译构建</title>
		<link>/how_to_build/</link>
					<comments>/how_to_build/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:43:18 +0000</pubDate>
				<category><![CDATA[文章]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[编译构建]]></category>
		<guid isPermaLink="false">/?p=308</guid>

					<description><![CDATA[如何编译构建 请首先到/language/zh/downloads/下载或克隆源码。 C++运行时库的构建 请参考<a class="moretag" href="/how_to_build/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<h2><span class="ez-toc-section" id="i">如何编译构建</span></h2>
<p id="section">请首先到<a href="/language/zh/downloads/#https://github.com/Tencent/behaviac">/language/zh/downloads/</a>下载或克隆源码。</p>
<h3 id="c"><span class="ez-toc-section" id="C">C++运行时库的构建</span></h3>
<p>请参考文档《<a href="/docs/zh/articles/build/">使用cmake构建C++版运行时库</a>》。</p>
<h4><span class="ez-toc-section" id="i-2">项目文件</span></h4>
<p>从3.6.33版本，我们提供了预先生成的项目文件，如下图：</p>
<p id="NgRlqmF"><img class="alignnone size-full wp-image-2062 " src="/wp-content/uploads/2017/07/img_5976b5154fe90.png" alt="" srcset="/wp-content/uploads/2017/07/img_5976b5154fe90.png 558w, /wp-content/uploads/2017/07/img_5976b5154fe90-300x110.png 300w" sizes="(max-width: 558px) 100vw, 558px" /></p>
<h3><span class="ez-toc-section" id="CUnity">C#和Unity运行时库的构建</span></h3>
<p>安装目录中的/integration/unity是基于Unity C#的单元测试项目。</p>
<p>自己的C#项目需要将目录/integration/unity/Assets/Scripts/behaviac/runtime下的所有源码直接复制过去，如下图所示：</p>
<p><img class="aligncenter size-full wp-image-1365" src="/wp-content/uploads/2016/05/unity_runtime.png" alt="unity_runtime" width="453" height="579" srcset="/wp-content/uploads/2016/05/unity_runtime.png 453w, /wp-content/uploads/2016/05/unity_runtime-235x300.png 235w" sizes="(max-width: 453px) 100vw, 453px" /></p>
<p>如果是Unity平台下的C#开发，还可以在Unity编辑器中导入/integration/behaviac.unitypackage包（安装完发布的BehaviacSetup_***.exe后，会在安装目录中的/integration文件夹中找到该behaviac.unitypackage包）。</p>
<h3><span class="ez-toc-section" id="i-3">编辑器的构建</span></h3>
<p>编辑器的源码目录结构，如下图所示：<br />
<img src="/img/faq/source_designer_path.png" alt="source_designer_path.png" /></p>
<p>请使用vs2010或以上打开并构建<code class="highlighter-rouge">tools/designer/BehaviacDesigner.sln</code>。</p>
]]></content:encoded>
					
					<wfw:commentRss>/how_to_build/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>VS项目中使用behaviac组件</title>
		<link>/cpp_include/</link>
					<comments>/cpp_include/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:44:04 +0000</pubDate>
				<category><![CDATA[文章]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[编译构建]]></category>
		<category><![CDATA[运行时]]></category>
		<guid isPermaLink="false">/?p=311</guid>

					<description><![CDATA[下载完behaviac组件的全部源码后，整个组件的目录结构，如下图所示： 将behaviac组件整合到自己的项目中时，可以通过两种方式使用behaviac组件：<a class="moretag" href="/cpp_include/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p id="cbehaviac">下载完behaviac组件的全部源码后，整个组件的目录结构，如下图所示：</p>
<p><img src="/img/tutorials/tutorial16/sourceFolder.png" alt="" /></p>
<p>将behaviac组件整合到自己的项目中时，可以通过两种方式使用behaviac组件：</p>
<ul>
<li>将全部源码（包括behaviac组件的所有<a href="https://github.com/Tencent/behaviac/blob/master/inc/behaviac">.h</a>和<a href="https://github.com/Tencent/behaviac/blob/master/src">.cpp</a>文件）全部复制到自己的游戏项目中。</li>
<li>单独编译behaviac组件库，生成lib文件，然后自己的项目包含.h文件和生成的.lib文件。</li>
</ul>
<p>对于上面的第二种用法，请先参考<a href="/docs/zh/tutorials/how_to_build/">如何编译构建</a>文档来编译构建behavaic组件。</p>
<p>在Windows平台，如果是使用VS来管理项目的，需要在VS的项目“Property Pages”-&gt;“Configuration Properties”-&gt;“C/C++”-&gt;“General”中的“Additional Include Directories”项中添加behaviac组件头文件（即图1中的inc文件夹）所在的路径，如下图所示：</p>
<p><img src="/img/tutorials/tutorial16/includeHeaderSettings.png" alt="" /></p>
<p>再在VS的项目“Property Pages”-&gt;“Configuration Properties”-&gt;“Linker”-&gt;“General”中的“Additional Library Directories”项中添加自己编译出的behaviac lib文件（即图1中的lib文件夹）所在的路径，如下图所示：</p>
<p><img src="/img/tutorials/tutorial16/includeLibSettings.png" alt="" /></p>
<p>最后在VS的项目“Property Pages”-&gt;“Configuration Properties”-&gt;“Linker”-&gt;“Input”中的“Additional Dependencies”项中添加自己编译出的behaviac lib文件，如下图所示：</p>
<p><img src="/img/tutorials/tutorial16/addLibSettings.png" alt="" /></p>
<p>注意：上图中的behaviac_debugdll_win32_vs2010.lib文件是用VS2010编译出来的，说明游戏项目也需要用VS2010来编译。如果你的游戏项目使用其他版本的VS，则编译behaviac组件也需要用相应版本的VS来编译。</p>
]]></content:encoded>
					
					<wfw:commentRss>/cpp_include/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>C++运行时端的使用上手</title>
		<link>/tutorial14_cpp_workflow/</link>
					<comments>/tutorial14_cpp_workflow/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:21:24 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[运行时]]></category>
		<guid isPermaLink="false">/?p=273</guid>

					<description><![CDATA[运行时（游戏）端使用行为树之前，需要确保行为树文件已经成功导出。 如何注册和导出类型信息请参考C++类型信息的注册和导出，如何导出行为树请参考导出和使用XML/<a class="moretag" href="/tutorial14_cpp_workflow/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p id="c">运行时（游戏）端使用行为树之前，需要确保行为树文件已经成功导出。</p>
<p>如何注册和导出类型信息请参考<a href="/docs/zh/tutorials/tutorial3_1_meta_cpp_register/">C++类型信息的注册和导出</a>，如何导出行为树请参考<a href="/docs/zh/tutorials/tutorial4_1_export_xml_bson/">导出和使用XML/BSON行为树</a>。</p>
<p>通过编辑器导出行为树文件后，运行时端的执行主要分为三个部分：</p>
<ul>
<li>初始化</li>
<li>循环更新</li>
<li>清理</li>
</ul>
<h3 id="section"><span class="ez-toc-section" id="1">1 初始化</span></h3>
<p>在游戏的初始化函数中，添加初始化behaviac组件所需的功能，例如注册Agent子类信息、设置行为树文件的加载路径和文件格式、创建Agent子类的实例、加载行为树并设置当前所需执行的行为树等。</p>
<p>如下代码所示：</p>
<div class="highlighter-rouge">
<pre class="highlight"><code><span class="n">bool</span> <span class="nf">InitBehavic</span><span class="p">(</span><span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">EFileFormat</span> <span class="n">ff</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Config</span><span class="o">::</span><span class="n">SetSocketBlocking</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Config</span><span class="o">::</span><span class="n">SetSocketPort</span><span class="p">(</span><span class="mi">8081</span><span class="p">);</span>

    <span class="n">behaviac</span><span class="o">::</span><span class="n">Agent</span><span class="o">::</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">CBTPlayer</span><span class="o">&gt;</span><span class="p">();</span>

    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">SetFilePath</span><span class="p">(</span><span class="s">"../test/demo_running/behaviac/exported"</span><span class="p">);</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">SetFileFormat</span><span class="p">(</span><span class="n">ff</span><span class="p">);</span>

    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">ExportMetas</span><span class="p">(</span><span class="s">"../test/demo_running/behaviac/demo_running.xml"</span><span class="p">);</span>

    <span class="c1">//behaviac::Agent::SetIdMask(kIdMask_Wolrd | kIdMask_Opponent);
</span>    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">SetDeltaFrames</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>

    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">bool</span> <span class="nf">InitPlayer</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">pszTreeName</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">g_player</span> <span class="o">=</span> <span class="n">behaviac</span><span class="o">::</span><span class="n">Agent</span><span class="o">::</span><span class="n">Create</span><span class="o">&lt;</span><span class="n">CBTPlayer</span><span class="o">&gt;</span><span class="p">();</span>

    <span class="n">bool</span> <span class="n">bRet</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
    <span class="n">bRet</span> <span class="o">=</span> <span class="n">g_player</span><span class="o">-&gt;</span><span class="n">btload</span><span class="p">(</span><span class="n">pszTreeName</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">bRet</span><span class="p">);</span>

    <span class="n">g_player</span><span class="o">-&gt;</span><span class="n">btsetcurrent</span><span class="p">(</span><span class="n">pszTreeName</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">bRet</span><span class="p">;</span>
<span class="p">}</span>

</code></pre>
</div>
<div class="note info">
<h5><span class="ez-toc-section" id="i">关于文件路径的说明</span></h5>
</div>
<ul>
<li>Workspace::SetFilePath指定的是编辑器中Workspace的导出路径，可以是绝对路径。当指定的是相对路径的时候，相对的是当前<strong>工作路径</strong>（一般都是运行程序所在目录）。</li>
<li>Agent::btload使用的文件名是相对于Workspace::SetFilePath指定的路径，没有扩展名，可以有目录结构的层次化文件名，如“node_test/selector_loop_ut_7”。在编辑器中打开某个行为树后，右键文件页选取“复制文件名”获取。</li>
</ul>
<p><img src="/img/tutorials/tutorial14/copy_filepath.png" alt="copy_filepath" /></p>
<ul>
<li>例如：
<ul>
<li>如果运行程序所在目录（或者VS里指定的工作路径$(TargetDir)）是”D:\Test\bin”</li>
<li>Workspace::SetFilePath指定的相对路径是“../behaviac/workspace/exported”</li>
<li>btload指定是“node_test/selector_loop_ut_7”</li>
<li>则workspace的导出路径实际是“D:/Test/behaviac/workspace/exported”，<br />
而相应的导出行为树文件是“D:/Test/behaviac/workspace/exported/node_test/selector_loop_ut_7.xml”或<br />
“D:/Test/behaviac/workspace/exported/node_test/selector_loop_ut_7.bson.bytes”。</li>
<li>具体是xml或bson则由Workspace::SetFileFormat确定。</li>
<li>当指定格式是cpp或c#的时候，导出的行为树是cpp或c#源码，已经编译构建进可执行程序，Agent::btload指定的文件名（跟xml的用法一样，无需修改btload的参数）只是用来标识该行为树的，从而代码可以据此创建相应的行为树，不像xml或bson格式的时候需要加载数据文件。</li>
</ul>
</li>
<li>如果Agent::btload加载失败，请注意检查当前路径，Workspace::SetFilePath设定的导出路径，以及Agent::btload指定的文件标识。还可以在当前路径里检查log文件<code class="highlighter-rouge">_behaviac_$_$_.log</code></li>
</ul>
<h3 id="section-1"><span class="ez-toc-section" id="2">2 循环更新</span></h3>
<p>在游戏的主循环中，添加执行Agent实例的行为树相关代码，也即通过调用Agent类的接口btexec()或Workspace类的接口Update()来执行行为树。</p>
<p>这两种执行方式的区别，请参考<a href="/docs/zh/tutorials/tutorial13_updateloop/">更新流程</a>。</p>
<p>如下代码样例所示：</p>
<div class="highlighter-rouge">
<pre class="highlight"><code>
<span class="kt">void</span> <span class="nf">UpdateLoop</span><span class="p">()</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">i</span>  <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="kt">int</span> <span class="n">frames</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">behaviac</span><span class="o">::</span><span class="n">EBTStatus</span> <span class="n">status</span> <span class="o">=</span> <span class="n">behaviac</span><span class="o">::</span><span class="n">BT_RUNNING</span><span class="p">;</span>

	<span class="k">while</span> <span class="p">(</span><span class="n">status</span> <span class="o">==</span> <span class="n">behaviac</span><span class="o">::</span><span class="n">BT_RUNNING</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"frame "</span> <span class="o">&lt;&lt;</span> <span class="o">++</span><span class="n">frames</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
		<span class="n">status</span> <span class="o">=</span> <span class="n">g_player</span><span class="o">-&gt;</span><span class="n">btexec</span><span class="p">();</span>
	<span class="p">}</span>
<span class="p">}</span>

</code></pre>
</div>
<h3 id="section-2"><span class="ez-toc-section" id="3">3 清理</span></h3>
<p>最后的清理过程，包括销毁Agent子类的实例，以及反注册Agent子类信息等。</p>
<p>如下代码样例所示：</p>
<div class="highlighter-rouge">
<pre class="highlight"><code>
<span class="kt">void</span> <span class="nf">CleanupPlayer</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Agent</span><span class="o">::</span><span class="n">Destroy</span><span class="p">(</span><span class="n">g_player</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">CleanupBehaviac</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Agent</span><span class="o">::</span><span class="n">UnRegister</span><span class="o">&lt;</span><span class="n">CBTPlayer</span><span class="o">&gt;</span><span class="p">();</span>

	<span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">Cleanup</span><span class="p">();</span>
<span class="p">}</span>

</code></pre>
</div>
<p>以上步骤的完整代码，请参考<a href="https://github.com/Tencent/behaviac/blob/master/test/demo_running/demo_running.cpp">demo_running.cpp</a>文件。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial14_cpp_workflow/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>导出和使用C++行为树</title>
		<link>/tutorial4_2_export_cpp/</link>
					<comments>/tutorial4_2_export_cpp/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:29:06 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[编辑器]]></category>
		<guid isPermaLink="false">/?p=284</guid>

					<description><![CDATA[在“导出行为树”对话框中，选择“C++ Behavior Exporter”，如下图所示： 点击上图中右侧的“…”设置按钮，在弹出的“C++导出设置”对话框中设<a class="moretag" href="/tutorial4_2_export_cpp/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<ul>
<li>在“导出行为树”对话框中，选择“C++ Behavior Exporter”，如下图所示：</li>
</ul>
<p><img class="aligncenter" src="/img/tutorials/tutorial4/exportCpp.png" alt="" /></p>
<ul>
<li>点击上图中右侧的“…”设置按钮，在弹出的“C++导出设置”对话框中设置生成文件所在的位置，并可以添加项目中游戏类（从Agent类派生而来）所在的.h头文件，添加的头文件将会被包含在生成的.cpp文件中，如下图所示：</li>
</ul>
<p><img class="aligncenter" src="/img/tutorials/tutorial4/cppExportSettings.png" alt="" /></p>
<ul>
<li>回到“导出行为树”对话框，点击“导出”按钮，开始导出<code class="highlighter-rouge">C++</code>文件。在指定的导出位置（默认为当前工作区的导出路径）会自动生成一个名为<code class="highlighter-rouge">behaviac_generated</code>的文件夹，里面生成了<code class="highlighter-rouge">behaviors</code>和<code class="highlighter-rouge">types</code>两个子文件夹，如图3所示：</li>
<li><code class="highlighter-rouge">behaviors</code>文件夹中含有<code class="highlighter-rouge">generated_behaviors.h</code>及其他单个的行为树<code class="highlighter-rouge">.inl</code>文件（如果没有勾选“导出统一文件？”，则对每一棵行为树都会生成独立的<code class="highlighter-rouge">.inl</code>文件，这些.inl文件会自动include在<code class="highlighter-rouge">generated_behaviors.h</code>文件中，无需在自己的项目中再include这些<code class="highlighter-rouge">.inl</code>文件，只需要include这个<code class="highlighter-rouge">generated_behaviors.h</code>文件即可）。</li>
<li><code class="highlighter-rouge">types</code>文件夹中含有<code class="highlighter-rouge">agentproperties.h</code>（为Agent类自定义的属性和方法，会扩展在该文件中）、<code class="highlighter-rouge">customizedtypes.h/customizedtypes.cpp</code>（自定义的枚举和结构体类型，会生成在这两个文件中）以及其他自定义<code class="highlighter-rouge">Agent</code>子类的文件（这些文件是为添加的<code class="highlighter-rouge">Agent</code>子类自动生成的<code class="highlighter-rouge">.h/.cpp</code>文件，需要程序员补充代码进一步实现这些<code class="highlighter-rouge">Agent</code>子类的逻辑）。</li>
</ul>
<p><img class="aligncenter" src="/img/tutorials/tutorial4/exportedCppFiles.png" alt="" /></p>
<ul>
<li>注意：这些自动生成的文件（除了上面提及的单个的行为树<code class="highlighter-rouge">.inl</code>文件之外）都需要包含到自己的游戏项目中，一起参与整个项目代码的编译和构建。</li>
<li>在项目中包含了这些自动生成的代码文件后，就可以与前面提及的<a href="/docs/zh/tutorials/tutorial4_1_export_xml_bson/">导出和使用XML/BSON行为树</a>一样的接口和方式加载使用这些C++文件，只是需要将文件格式改为<code class="highlighter-rouge">EFF_cpp</code>：</li>
</ul>
<div class="highlighter-rouge">
<pre class="highlight"><code>
<span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">SetFileFormat</span><span class="p">(</span><span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">EFF_cpp</span><span class="p">);</span>

</code></pre>
</div>
<div class="section-nav"></div>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial4_2_export_cpp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C++运行时端中元信息的注册和导出</title>
		<link>/tutorial3_1_meta_cpp_register/</link>
					<comments>/tutorial3_1_meta_cpp_register/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:23:51 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[运行时]]></category>
		<guid isPermaLink="false">/?p=276</guid>

					<description><![CDATA[behaviac组件的基本运作机制就是在运行时端（C++）和编辑器通过元信息进行交互，如图1所示。其中，元信息里面包含了类自身的描述、属性、方法及类的实例等。 <a class="moretag" href="/tutorial3_1_meta_cpp_register/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p id="c">behaviac组件的基本运作机制就是在运行时端（C++）和编辑器通过元信息进行交互，如图1所示。其中，元信息里面包含了类自身的描述、属性、方法及类的实例等。</p>
<p><img class="aligncenter" src="/img/overview/meta.png" alt="" /></p>
<p style="text-align: center;">图1 基于元信息的编辑器和运行时端的交互</p>
<p>在运行时端，也即游戏代码端，通过注册（C++通过宏的方式）并导出供行为树引擎和编辑器使用的XML元信息。运行时端主要是由程序员编写Agent的子类及其属性和方法，然后调用相关接口将这些元信息导出，就可以在编辑器中对这些元信息进行使用。</p>
<p>在编辑器中也可以创建和编辑元信息。在项目开始初期，也就是程序员还没把代码写出来之前，策划就可以自己手动的创建一些Agent子类、属性和方法等元信息。这样可以加速游戏原型的创建，也就是策划不用等程序员，就可以进行游戏原型的编辑。</p>
<p>整个工作流程主要分为以下几个步骤：</p>
<h3 id="section">1 注册元信息</h3>
<ul>
<li>在.h文件中，根据项目需要按以下步骤编写自己的游戏类：
<ul>
<li>首先需要包含头文件#include “behaviac/behaviac.h”。</li>
<li>该类需要从behaviac::Agent基类继承。</li>
<li>首先用宏DECLARE_BEHAVIAC_AGENT声明该类及其父类，用于行为树引擎内部的反射系统所需的类型信息。</li>
<li>为该类添加必要的属性和方法等。</li>
</ul>
</li>
</ul>
<p>如下代码样例所示：</p>
<div class="highlighter-rouge">
<pre class="highlight"><code>
<span class="cp">#include "behaviac/behaviac.h"
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">behaviac</span><span class="p">;</span>

<span class="k">class</span> <span class="nc">CBTPlayer</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Agent</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
    <span class="n">DECLARE_BEHAVIAC_AGENT</span><span class="p">(</span><span class="n">CBTPlayer</span><span class="p">,</span> <span class="n">Agent</span><span class="p">);</span>

    <span class="n">CBTPlayer</span><span class="p">();</span>
    <span class="k">virtual</span> <span class="o">~</span><span class="n">CBTPlayer</span><span class="p">();</span>

    <span class="kt">time_t</span> <span class="n">GetCurTime</span><span class="p">();</span>
    <span class="n">bool</span> <span class="n">Condition</span><span class="p">();</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">EBTStatus</span> <span class="n">Action1</span><span class="p">();</span>
    <span class="n">EBTStatus</span> <span class="n">Action3</span><span class="p">();</span>

<span class="k">private</span><span class="o">:</span>
    <span class="kt">int</span>                 <span class="n">m_iX</span><span class="p">;</span>
    <span class="kt">int</span>                 <span class="n">m_iY</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">int</span>        <span class="n">m_iBaseSpeed</span><span class="p">;</span>
    <span class="kt">int</span>					<span class="n">m_Frames</span><span class="p">;</span>
<span class="p">};</span>

</code></pre>
</div>
<ul>
<li>在.cpp文件中，通过一系列宏来注册该类自身的描述及其属性与方法：
<ul>
<li>宏BEGIN_PROPERTIES_DESCRIPTION和END_PROPERTIES_DESCRIPTION表示类型信息注册的开始和结束。</li>
<li>宏CLASS_DISPLAYNAME和CLASS_DESC用于注册类自身的显示名和描述。</li>
<li>宏REGISTER_PROPERTY用于注册类的属性，可以通过.DISPLAYNAME的追加方式为属性添加显示名，通过.DESC的追加方式为属性添加描述。</li>
<li>宏REGISTER_METHOD用于注册类的方法，可以通过.DISPLAYNAME的追加方式为方法添加显示名，通过.DESC的追加方式为方法添加描述，通过.PARAM_DISPLAY_INFO的追加方式为参数添加显示名和描述等。如果参数类型是数值类型（例如int、unsigned int、float等），.PARAM_DISPLAY _INFO还可以用来指定参数的有效范围。</li>
</ul>
</li>
</ul>
<p>如下代码样例所示：</p>
<div class="highlighter-rouge">
<pre class="highlight"><code>
<span class="n">BEGIN_PROPERTIES_DESCRIPTION</span><span class="p">(</span><span class="n">CBTPlayer</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">REGISTER_PROPERTY</span><span class="p">(</span><span class="n">m_iBaseSpeed</span><span class="p">);</span>

	<span class="n">REGISTER_METHOD</span><span class="p">(</span><span class="n">Condition</span><span class="p">);</span>
	<span class="n">REGISTER_METHOD</span><span class="p">(</span><span class="n">Action1</span><span class="p">);</span>
	<span class="n">REGISTER_METHOD</span><span class="p">(</span><span class="n">Action3</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">END_PROPERTIES_DESCRIPTION</span><span class="p">()</span>

</code></pre>
</div>
<h3 id="section-1">2 导出元信息</h3>
<p>注册完类信息之后，按以下步骤导出元数据文件：</p>
<ul>
<li>在初始化函数里，添加Agent::Register&lt;***&gt;()用于注册类信息到引擎库中。</li>
<li>通过Agent::RegisterInstanceName&lt;***&gt;(…)来注册类的实例名。</li>
<li>调用Workspace::GetInstance()-&gt;SetFilePath(…)设置元信息文件导出的位置。</li>
<li>调用Workspace::GetInstance()-&gt;ExportMetas(…)导出元信息文件。</li>
<li>在释放函数里，添加Agent::Unregister&lt;***&gt;()用于释放类型的注册信息。</li>
</ul>
<p>如下代码样例所示：</p>
<div class="highlighter-rouge">
<pre class="highlight"><code>
<span class="n">bool</span> <span class="nf">InitBehavic</span><span class="p">(</span><span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">EFileFormat</span> <span class="n">ff</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Config</span><span class="o">::</span><span class="n">SetSocketBlocking</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Config</span><span class="o">::</span><span class="n">SetSocketPort</span><span class="p">(</span><span class="mi">8081</span><span class="p">);</span>

    <span class="n">behaviac</span><span class="o">::</span><span class="n">Agent</span><span class="o">::</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">CBTPlayer</span><span class="o">&gt;</span><span class="p">();</span>

    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">SetFilePath</span><span class="p">(</span><span class="s">"../test/demo_running/behaviac/exported"</span><span class="p">);</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">SetFileFormat</span><span class="p">(</span><span class="n">ff</span><span class="p">);</span>

    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">ExportMetas</span><span class="p">(</span><span class="s">"../test/demo_running/behaviac/demo_running.xml"</span><span class="p">);</span>

    <span class="c1">//behaviac::Agent::SetIdMask(kIdMask_Wolrd | kIdMask_Opponent);
</span>    <span class="n">behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">SetDeltaFrames</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>

    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">CleanupBehaviac</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">behaviac</span><span class="o">::</span><span class="n">Agent</span><span class="o">::</span><span class="n">UnRegister</span><span class="o">&lt;</span><span class="n">CBTPlayer</span><span class="o">&gt;</span><span class="p">();</span>
<span class="n">    behaviac</span><span class="o">::</span><span class="n">Workspace</span><span class="o">::</span><span class="n">GetInstance</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">Cleanup</span><span class="p">();</span>
<span class="p">}</span>

</code></pre>
</div>
<p>更多细节可以参考behaviac组件C++源码中附带的test/demo_running工程的<a href="https://github.com/Tencent/behaviac/blob/master/test/demo_running/demo_running.cpp">demo_running.cpp</a>文件。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial3_1_meta_cpp_register/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>C#运行时端中元信息的注册和导出</title>
		<link>/tutorial3_2_meta_cs_register/</link>
					<comments>/tutorial3_2_meta_cs_register/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:25:57 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<category><![CDATA[unity]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[运行时]]></category>
		<guid isPermaLink="false">/?p=278</guid>

					<description><![CDATA[behaviac组件的基本运作机制就是在运行时端（C#）和编辑器通过元信息进行交互，如图1所示。其中，元信息里面包含了类自身的描述、属性、方法及类的实例等。 图<a class="moretag" href="/tutorial3_2_meta_cs_register/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p id="c-">behaviac组件的基本运作机制就是在运行时端（C#）和编辑器通过元信息进行交互，如图1所示。其中，元信息里面包含了类自身的描述、属性、方法及类的实例等。</p>
<p><img class="aligncenter" src="/img/overview/meta.png" alt="" /></p>
<p style="text-align: center;">图1 基于元信息的编辑器和运行时端的交互</p>
<p>在运行时端，也即游戏代码端，通过注册（C#通过标记Attribute的方式）并导出供行为树引擎和编辑器使用的XML元信息。运行时端主要是由程序员编写Agent的子类及其属性和方法，然后调用相关接口将这些元信息导出，就可以在编辑器中对这些元信息进行使用。</p>
<p>在编辑器中也可以创建和编辑元信息。在项目开始初期，也就是程序员还没把代码写出来之前，策划就可以自己手动的创建一些Agent子类、属性和方法等元信息。这样可以加速游戏原型的创建，也就是策划不用等程序员，就可以进行游戏原型的编辑。</p>
<p>整个工作流程主要分为以下几个步骤：</p>
<h3 id="section">1 注册元信息</h3>
<p>C#中编写的游戏类从behaviac.Agent派生，并通过相关的Attribute来标记元信息：</p>
<ul>
<li>类：TypeMetaInfo</li>
<li>成员属性：MemberMetaInfo</li>
<li>成员方法：MethodMetaInfo</li>
</ul>
<p>这3个类都可以接受诸如显示名字，描述等更多参数。详细请参考代码。</p>
<p>如下代码样例所示：</p>
<figure class="highlight">
<pre><code class="language-cs" data-lang="cs"><span class="na">[behaviac.TypeMetaInfo()]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">AgentNodeTest</span> <span class="p">:</span> <span class="n">behaviac</span><span class="p">.</span><span class="n">Agent</span>
<span class="p">{</span>
    <span class="p">[</span><span class="n">behaviac</span><span class="p">.</span><span class="nf">MemberMetaInfo</span><span class="p">()]</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">testVar_0</span> <span class="p">=</span> <span class="p">-</span><span class="m">1</span><span class="p">;</span>

    <span class="p">[</span><span class="n">behaviac</span><span class="p">.</span><span class="nf">MemberMetaInfo</span><span class="p">(</span><span class="s">"testVar_1"</span><span class="p">,</span> <span class="s">"testVar_1 property"</span><span class="p">,</span> <span class="m">100</span><span class="p">)]</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">testVar_1</span> <span class="p">=</span> <span class="p">-</span><span class="m">1</span><span class="p">;</span>

    <span class="p">[</span><span class="n">behaviac</span><span class="p">.</span><span class="nf">MemberMetaInfo</span><span class="p">()]</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="n">testVar_2</span> <span class="p">=</span> <span class="p">-</span><span class="m">1.0f</span><span class="p">;</span>

    <span class="p">[</span><span class="n">behaviac</span><span class="p">.</span><span class="nf">MemberMetaInfo</span><span class="p">()]</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">waiting_timeout_interval</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>

    <span class="p">[</span><span class="n">behaviac</span><span class="p">.</span><span class="nf">MemberMetaInfo</span><span class="p">()]</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="n">testVar_str_0</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Empty</span><span class="p">;</span>

    <span class="k">public</span> <span class="kt">bool</span> <span class="n">m_bCanSee</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>

    <span class="p">[</span><span class="n">behaviac</span><span class="p">.</span><span class="nf">MethodMetaInfo</span><span class="p">()]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">setEventVarInt</span><span class="p">(</span><span class="kt">int</span> <span class="n">var</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">event_test_var_int</span> <span class="p">=</span> <span class="n">var</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="p">[</span><span class="n">behaviac</span><span class="p">.</span><span class="nf">MethodMetaInfo</span><span class="p">()]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">setEventVarBool</span><span class="p">(</span><span class="kt">bool</span> <span class="n">var</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">event_test_var_bool</span> <span class="p">=</span> <span class="n">var</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre>
</figure>
<h3 id="section-1">2 导出元信息</h3>
<p>由于C#代码中已经包含了各种Attribute来描述元信息，因而导出相比C++要简单：</p>
<ul>
<li>Agent子类的实例通过Agent.RegisterInstanceName&lt;***&gt;(…)来进行注册。</li>
<li>调用Workspace.Instance.FilePath设置元信息文件导出的位置。</li>
<li>调用Workspace.Instance.ExportMetas(…)导出元信息文件。</li>
</ul>
<p>如下代码样例所示：</p>
<figure class="highlight">
<pre><code class="language-cs" data-lang="cs"><span class="k">public</span> <span class="kt">bool</span> <span class="nf">Init</span> <span class="p">()</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ms_fileSystem</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">ms_fileSystem</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">BehaviacFileManager</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="c1">//&lt; write log file
</span>    <span class="n">behaviac</span><span class="p">.</span><span class="n">Config</span><span class="p">.</span><span class="n">IsLogging</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span>
    <span class="c1">//behaviac.Config.IsSocketing = false;
</span>
    <span class="n">behaviac</span><span class="p">.</span><span class="n">Workspace</span><span class="p">.</span><span class="n">Instance</span><span class="p">.</span><span class="n">FilePath</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">WorkspaceExportPath</span><span class="p">;</span>
    <span class="n">behaviac</span><span class="p">.</span><span class="n">Workspace</span><span class="p">.</span><span class="n">Instance</span><span class="p">.</span><span class="n">FileFormat</span> <span class="p">=</span> <span class="n">behaviac</span><span class="p">.</span><span class="n">Workspace</span><span class="p">.</span><span class="n">EFileFormat</span><span class="p">.</span><span class="n">EFF_xml</span><span class="p">;</span>

    <span class="c1">//register names
</span>    <span class="n">behaviac</span><span class="p">.</span><span class="n">Agent</span><span class="p">.</span><span class="n">RegisterInstanceName</span><span class="p">&lt;</span><span class="n">GameLevelCommon</span><span class="p">&gt;(</span><span class="s">"GameLevel"</span><span class="p">);</span>
    <span class="n">behaviac</span><span class="p">.</span><span class="n">Workspace</span><span class="p">.</span><span class="n">Instance</span><span class="p">.</span><span class="nf">ExportMetas</span><span class="p">(</span><span class="s">"behaviac/workspace/xmlmeta/BattleCityMeta.xml"</span><span class="p">);</span>

    <span class="n">behaviac</span><span class="p">.</span><span class="n">Debug</span><span class="p">.</span><span class="nf">Log</span><span class="p">(</span><span class="s">"Behaviac meta data export over."</span><span class="p">);</span>
    <span class="n">behaviac</span><span class="p">.</span><span class="n">Agent</span><span class="p">.</span><span class="nf">SetIdMask</span><span class="p">(</span><span class="m">0xffffffff</span><span class="p">);</span>

    <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">void</span> <span class="nf">Uninit</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">behaviac</span><span class="p">.</span><span class="n">Workspace</span><span class="p">.</span><span class="n">Instance</span><span class="p">.</span><span class="nf">Cleanup</span><span class="p">();</span>
<span class="p">}</span></code></pre>
</figure>
<p>更多细节可以参考behaviac组件C#源码中附带的integration/BattleCityDemo工程的<a href="https://github.com/Tencent/behaviac/blob/master/integration/BattleCityDemo/Assets/Scripts/BehaviacSystem.cs">BehaviacSystem.cs</a>文件。</p>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial3_2_meta_cs_register/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>导出和使用C#行为树</title>
		<link>/tutorial4_3_export_cs/</link>
					<comments>/tutorial4_3_export_cs/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:29:49 +0000</pubDate>
				<category><![CDATA[3.5]]></category>
		<category><![CDATA[unity]]></category>
		<category><![CDATA[上手]]></category>
		<category><![CDATA[编辑器]]></category>
		<guid isPermaLink="false">/?p=286</guid>

					<description><![CDATA[在“导出行为树”对话框中，选择“C# Behavior Exporter”，如下图所示： 点击上图中右侧的“…”设置按钮，在弹出的“C#导出设置”对话框中设置导<a class="moretag" href="/tutorial4_3_export_cs/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<ul>
<li>在“导出行为树”对话框中，选择“C# Behavior Exporter”，如下图所示：</li>
</ul>
<p><img class="aligncenter" src="/img/tutorials/tutorial4/exportCs.png" alt="" /></p>
<ul>
<li>点击上图中右侧的“…”设置按钮，在弹出的“C#导出设置”对话框中设置导出文件所在的位置，如图2所示：</li>
</ul>
<p><img class="aligncenter" src="/img/tutorials/tutorial4/csExportSettings.png" alt="" /></p>
<ul>
<li>回到“导出行为树”对话框，点击“导出”按钮，开始导出<code class="highlighter-rouge">C#</code>文件。在指定的导出位置（默认为当前工作区的导出路径）会自动生成一个名为<code class="highlighter-rouge">behaviac_generated</code>的文件夹，里面生成了<code class="highlighter-rouge">behaviors</code>和<code class="highlighter-rouge">types</code>两个子文件夹，如图3所示：<img class="aligncenter" src="/img/tutorials/tutorial4/exportedCsFiles.png" alt="" /></li>
<li><code class="highlighter-rouge">behaviors</code>文件夹含有<code class="highlighter-rouge">generated_behaviors.cs</code>及其他单个的行为树<code class="highlighter-rouge">.cs</code>文件（如果没有勾选“导出统一文件？”，则对每一棵行为树都会生成独立的<code class="highlighter-rouge">.cs</code>文件）。</li>
<li><code class="highlighter-rouge">types</code>文件夹中含有<code class="highlighter-rouge">agentproperties.cs</code>（为<code class="highlighter-rouge">Agent</code>类自定义的属性和方法，会扩展在该文件中）、<code class="highlighter-rouge">customizedtypes.cs</code>（自定义的枚举和结构体类型，会生成在这个文件中）以及其他的<code class="highlighter-rouge">Agent</code>子类的文件（这些文件是为添加的<code class="highlighter-rouge">Agent</code>子类自动生成的<code class="highlighter-rouge">.cs</code>文件，需要程序员补充代码进一步实现这些<code class="highlighter-rouge">Agent</code>子类的逻辑），这些自动生成的文件都需要包含到自己的游戏项目中。</li>
</ul>
<ul>
<li>注意：这些自动生成的文件都需要包含到自己的游戏项目中，一起参与整个项目代码的编译和构建。</li>
<li>在项目中包含了这些自动生成的<code class="highlighter-rouge">.cs</code>文件后，就可以与前面提及的<a href="/docs/zh/tutorials/tutorial4_1_export_xml_bson/">导出和使用XML/BSON行为树</a>一样的接口和方式加载使用这些文件，只是需要将文件格式改为<code class="highlighter-rouge">EFF_cs</code>：</li>
</ul>
<figure class="highlight">
<pre><code class="language-cs" data-lang="cs"><span class="n">behaviac</span><span class="p">.</span><span class="n">Workspace</span><span class="p">.</span><span class="n">Instance</span><span class="p">.</span><span class="n">FileFormat</span> <span class="p">=</span> <span class="n">behaviac</span><span class="p">.</span><span class="n">Workspace</span><span class="p">.</span><span class="n">EFileFormat</span><span class="p">.</span><span class="n">EF</span></code></pre>
</figure>
]]></content:encoded>
					
					<wfw:commentRss>/tutorial4_3_export_cs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
