<?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/manual/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, 10 Oct 2017 04:20:07 +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>/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>/selector/</link>
					<comments>/selector/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Wed, 11 May 2016 10:07:34 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=218</guid>

					<description><![CDATA[Selector 节点是 BT 中传统的组合节点之一。 该节点以给定的顺序依次调用其子节点，直到 其中一个成功返回，那么该节点也返回成功。如果所有的子节点都失败<a class="moretag" href="/selector/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p><img src="/img/references/selector.png" alt="selector" /></p>
<p>Selector 节点是 BT 中传统的组合节点之一。 该节点以给定的顺序依次调用其子节点，直到<br />
其中一个成功返回，那么该节点也返回成功。如果所有的子节点都失败，那么该节点也失败。</p>
<p>Selector 实现了或（‘||’）的功能。 我们知道表达式 R=A||B||C||D 执行的时候首先执行 A，如果<br />
A 是 true 则返回 true，如果 A 是 false 则执行 B，如果 B 是 true 则返回 true，否则如果 B 是<br />
false 则执行 C，如果 C 是 true 则返回 true，否则如果 C 是 false 则执行 D， 并且返回 D 的值。<br />
最一般的意义上， Selector 节点实现了一个选择，从子节点中选择一个。 Selector 节点优先<br />
选择了排在前面的子节点。</p>
<p>此外， Selector 上还可以添加‘中断条件’作为终止执行的条件。上图中红框所示就是可选的‘中断条件’。该‘中断条件’在每处理下一个子节点的时候被检查，当为true时，则不再继续，返回失败（Failure）。</p>
<p>具体的执行逻辑可以查看 <a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/selector.cpp">behaviortree/nodes/composites/selector.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/selector/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>并行节点</title>
		<link>/parallel/</link>
					<comments>/parallel/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Wed, 25 May 2016 08:31:58 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=429</guid>

					<description><![CDATA[并行（Parallel）节点在一般意义上是并行的执行其子节点，即“一边做A，一边做B”，如下图所示： 在选择或序列节点中，是顺序的一个接一个的执行其子节点，上一<a class="moretag" href="/parallel/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>并行（Parallel）节点在一般意义上是并行的执行其子节点，即“一边做A，一边做B”，如下图所示：</p>
<p id="FgwGTQU"><img class="size-full wp-image-1940  aligncenter" src="/wp-content/uploads/2017/04/img_58fdc12123513.png" alt="" srcset="/wp-content/uploads/2017/04/img_58fdc12123513.png 530w, /wp-content/uploads/2017/04/img_58fdc12123513-300x159.png 300w" sizes="(max-width: 530px) 100vw, 530px" /></p>
<p>在选择或序列节点中，是顺序的一个接一个的执行其子节点，上一个子节点执行结束后，根据其状态是否执行接下来的子节点。而并行节点在逻辑上是“同时”并行的执行所有子节点（但实际也是从上往下依次执行），然后根据所有子节点的状态决定本身的状态。</p>
<p><strong>注意：</strong>并行节点每帧都有可能执行所有的子树，大量使用的时候请注意其性能。</p>
<p>如何根据所有子节点的返回状态，来决定并行节点本身的状态呢？并行节点有几个重要属性可以配置，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/parallelproperties.png" alt="parallelproperties" /></p>
<ul>
<li><strong>失败条件：</strong>决定并行节点在什么条件下是失败的</li>
<li><strong>成功条件：</strong>决定并行节点在什么条件下是成功的</li>
<li><strong>子节点结束继续条件：</strong>子节点结束后是重新再循环执行，还是结束后不再执行</li>
<li><strong>退出行为：</strong>当并行节点的成功或失败条件满足并返回成功或失败后，是否需要终止掉其他还在运行的子节点</li>
<li>当子节点执行状态既不满足失败条件，也不满足成功条件，且无Running状态子节点时，并行节点将直接返回Failure</li>
</ul>
<p>在序列节点中，假设其子节点包括了条件节点和其他节点。那么，条件节点实际上是作为其他节点的前提条件，只有条件节点返回Success，下面的其他节点才会得到执行。</p>
<p>并行节点可以用来实现所谓的“上下文相关的前提条件”（context precondition），如下图所示：<img src="file:///C:\Users\cainhuang\AppData\Roaming\Tencent\Users\48016464\QQ\WinTemp\RichOle\&#96;95YXVWT)4SIK20T]5NH&#96;K5.png" /></p>
<p><img class="aligncenter size-full wp-image-1941" src="/wp-content/uploads/2016/05/95YXVWT4SIK20T5NHK5.png" alt="" width="521" height="186" srcset="/wp-content/uploads/2016/05/95YXVWT4SIK20T5NHK5.png 521w, /wp-content/uploads/2016/05/95YXVWT4SIK20T5NHK5-300x107.png 300w" sizes="(max-width: 521px) 100vw, 521px" /></p>
<p>并行节点配置条件节点和其他节点，并且失败条件是缺省的配置FAIL_ON_ONE，那么只有当条件节点成功的时候其他节点才被执行，从而条件节点事实上是其他节点的前提条件。</p>
<p><strong>注意：</strong>作为前提条件的这种用法是不严谨的，当条件失败的时候，在并行节点返回失败之前，后续的其他节点会多执行一次。所以，请使用“<a href="/attachment/">前置</a>”附件来实现这种前置条件的需求。</p>
<p>与序列节点+条件节点方式的不同之处在于，序列节点实现的前提条件只是“进入”其他节点的前提条件，一旦首次进入并开始执行其他节点后，就不再检查该前提条件了。而并行节点实现的前提条件是上下文相关的，不但首次进入并开始执行前需要检查，之后每次执行也都要检查。</p>
<p>具体的执行逻辑可以查看 <a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/parallel.cpp">behaviortree/nodes/composites/parallel.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/parallel/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>动作节点</title>
		<link>/action/</link>
					<comments>/action/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Mon, 11 Apr 2016 09:10:18 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=128</guid>

					<description><![CDATA[动作（Action）节点在behaviac中几乎是最重要的节点，如下图所示： 动作节点通常对应Agent的某个方法（Method），可以从下拉列表里为其选择方法<a class="moretag" href="/action/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>动作（Action）节点在behaviac中几乎是最重要的节点，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/action.png" alt="action" /></p>
<p>动作节点通常对应Agent的某个方法（Method），可以从下拉列表里为其选择方法，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/action_prop.png" alt="action" /></p>
<p>在设置其方法后，需进一步设置其“决定状态的选项（Status Option）”或“决定状态的函数（Status Functor）”，如上图所示。如果没有正确配置，则视为错误不能被导出。</p>
<ul>
<li>“决定状态的选项”：不管动作的方法的返回值是什么，都强制返回设定的EBTStatus值（即Success、Failure或Running）。</li>
<li>“决定状态的函数”：将动作的方法的返回值从不是EBTStatus类型，转换为执行行为树所需要的EBTStatus值（即Success、Failure或Running）。</li>
</ul>
<p>有三种设置来决定每次执行动作节点后的状态（Success、Failure或Running）：</p>
<ul>
<li>如果动作节点的方法返回EBTStatus值，那么该值就直接作为动作节点的状态，“决定状态的选项”和“决定状态的函数”将被禁用无需设置。</li>
<li>否则，需要设置“决定状态的选项”：当选择Invalid值时，表明需要进一步设置“决定状态的函数”，否则禁用“决定状态的函数”项，并直接使用“决定状态的选项”所选择的值（Success、Failure或Running），表示该方法执行完毕后，动作节点将返回这个设置的值。</li>
<li>在“决定状态的函数”项中选择的函数，其返回值必然是EBTStatus，作为动作节点的状态。该函数只有一个或者没有参数，当动作节点的方法无返回值时，该函数没有参数，当动作节点的方法有返回值时，该函数唯一参数的类型为动作节点方法的返回值类型。也即，
<ul>
<li>当方法的原型是void Method(…)的时候，“决定状态的函数”的原型为：EBTStatus StatusFunctor()。</li>
<li>当方法的原型是ReturnType Method(…)的时候，“决定状态的函数”的原型为：EBTStatus StatusFunctor(ReturnType param)。</li>
</ul>
</li>
</ul>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/action.cpp">behaviortree/nodes/actions/action.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/action/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>条件节点</title>
		<link>/condition/</link>
					<comments>/condition/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:02:06 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=242</guid>

					<description><![CDATA[条件（Condition）节点对左右参数进行比较，如下图所示： 图1 条件节点 条件节点根据比较结果返回成功或失败，但永远不会返回正在执行（Running）： <a class="moretag" href="/condition/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>条件（Condition）节点对左右参数进行比较，如下图所示：</p>
<p><img src="/img/references/condition.png" alt="condition" /></p>
<p>图1 条件节点</p>
<p>条件节点根据比较结果返回成功或失败，但永远不会返回正在执行（Running）：</p>
<ul>
<li>如果结果为真，则返回成功。</li>
<li>如果结果为假，则返回失败。</li>
</ul>
<p>通常左参数是Agent的某个属性或某个有返回值的方法，用户可以从下拉列表里选择，右参数是相应类型的常数、Agent的某个属性或某个有返回值的方法，如下图所示：</p>
<p><img src="/img/references/condition_prop.png" alt="condition" /></p>
<p>图2 条件节点的属性</p>
<p>条件节点没有提供取反的属性。如果需要取反，请用《<a href="/docs/zh/references/decorator/">非（Not）节点</a>》来装饰。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/conditions/condition.cpp">behaviortree/nodes/conditions/condition.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/condition/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>装饰节点</title>
		<link>/decorator/</link>
					<comments>/decorator/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:06:29 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=248</guid>

					<description><![CDATA[概述 装饰节点作为控制分支节点，必须且只接受一个子节点。装饰节点的执行首先执行子节点，并根据自身的控制逻辑以及子节点的返回结果决定自身的状态。 装饰节点都有属性<a class="moretag" href="/decorator/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<h2><span class="ez-toc-section" id="i">概述</span></h2>
<p>装饰节点作为控制分支节点，必须且只接受一个子节点。装饰节点的执行首先执行子节点，并根据自身的控制逻辑以及子节点的返回结果决定自身的状态。</p>
<p>装饰节点都有属性“子节点结束时作用（DecorateChildEnds）”可以配置，如果该值配置为真，则仅当子节点结束（成功或失败）的时候，装饰节点的装饰逻辑才起作用。</p>
<h2 id="log"><span class="ez-toc-section" id="Log">输出消息（Log）节点</span></h2>
<p>输出消息节点作为调试的辅助工具，执行完子节点后，输出配置的消息，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/log.png" alt="log" /></p>
<p>可以在“输出消息”属性中设置想输出的任何消息，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/log_prop.png" alt="log" /></p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorlog.cpp">behaviortree/nodes/decorators/decoratorlog.cpp</a></p>
<h2 id="not"><span class="ez-toc-section" id="Not">非（Not）节点</span></h2>
<p>非节点将子节点的返回值取反，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/not.png" alt="not" /></p>
<p>类似于逻辑“非”操作，非节点对子节点的返回值执行如下操作：</p>
<ul>
<li>如果子节点失败，那么此节点返回成功。</li>
<li>如果子节点成功，那么此节点返回失败。</li>
<li>如果子节点返回正在执行，则同样返回正在执行。</li>
</ul>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratornot.cpp">behaviortree/nodes/decorators/decoratornot.cpp</a></p>
<h2 id="loop"><span class="ez-toc-section" id="Loop">循环（Loop）节点</span></h2>
<p>循环节点循环执行子节点指定的次数，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/loop.png" alt="loop" /></p>
<p>如下图可以配置循环节点的相关参数：</p>
<p><img class="aligncenter size-full wp-image-1488" src="/wp-content/uploads/2016/05/loop.png" alt="" width="476" height="214" srcset="/wp-content/uploads/2016/05/loop.png 476w, /wp-content/uploads/2016/05/loop-300x135.png 300w" sizes="(max-width: 476px) 100vw, 476px" /></p>
<ul>
<li>次数：如果次数配置为-1，则视为无限循环，总是返回运行。否则循环执行子节点指定的次数然后返回成功，在指定次数之前则返回运行。</li>
<li>此循环次数可以是常数，也可以是变量，当是变量的时候，每次enter的时候此循环次数被赋值，也就是每次enter的时候，循环的次数就被确定了。之后再更改该变量的值在本次循环内将不起作用，但是exit后再enter的时候会起作用。</li>
<li>一帧内结束：如果选择了‘一帧内结束’，次数不可以配置为-1，节点阻塞，直到子节点在一帧内执行指定的次数后返回成功。
<ul>
<li>然而如果子节点失败了，不会执行指定次数就直接返回失败。</li>
<li>如果子节点一直返回运行，则本节点一直阻塞。但如果“子节点结束时作用”不为真，则不会阻塞。</li>
<li>在‘一帧内结束’的情况下，本节点只能成功或失败，不会返回运行。</li>
<li>‘一帧内结束’的配置只在3.5.4及以后的版本中才有实现。用以取代<a href="/language/zh/decorator/#repeat">重复节点</a></li>
</ul>
</li>
</ul>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorloop.cpp">behaviortree/nodes/decorators/decoratorloop.cpp</a></p>
<h2 id="loopuntil"><span class="ez-toc-section" id="LoopUntil">循环直到（LoopUntil）节点</span></h2>
<p>循环直到节点在指定的次数到达后返回成功，在指定的次数到达前一直返回正在执行。如果指定的次数小于0，则表示无限循环，总是返回正在执行。如下图所示：</p>
<p><img class="aligncenter" src="/img/references/loopuntil.png" alt="loopuntil" /></p>
<p>循环直到节点除了像循环节点可以配置循环的次数，还有一个属性“直到子树”需要配置，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/loopuntil_prop.png" alt="loopuntil_prop" /></p>
<p>循环直到节点有两个结束条件，指定的“循环次数”到达或者子树的返回值与配置的“直到子树”值一样：</p>
<ul>
<li>指定的“循环次数”到达的时候，则返回成功。</li>
<li>指定的“循环次数”小于0的时候，则是无限循环，等同于只检查子树的返回值是否满足。</li>
<li>子树的返回值满足的时候：
<ul>
<li>如果“直到子树”设置为真，意味着直到子树返回成功，也返回成功。</li>
<li>如果“直到子树”设置为假，意味着直到子树返回失败，也返回失败。</li>
</ul>
</li>
</ul>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorloopuntil.cpp">behaviortree/nodes/decorators/decoratorloopuntil.cpp</a></p>
<h2 id="repeat"><span class="ez-toc-section" id="Repeat">重复（Repeat）节点</span></h2>
<p id="repeat">重复（Repeat）节点只在3.5.4以前的版本中才有。3.5.4及以后的版本请使用<a href="/language/zh/decorator/#loop">循环节点</a>，并且选上‘一帧内结束’</p>
<p>重复节点根据指定的次数，在一次更新过程中重复执行子节点然后返回，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/repeat.png" alt="repeat" /></p>
<p>重复节点根据子节点的返回值相应的返回：</p>
<ul>
<li>如果子节点失败了，则返回失败。</li>
<li>如果子节点一直运行，则本节点一直阻塞。但如果“子节点结束时作用”不为真，则不会阻塞。</li>
<li>其他情况，则返回成功。</li>
<li>本节点只能成功或失败，不会返回运行。</li>
</ul>
<p>重复节点可以配置重复执行的“次数”和“子节点结束时作用”，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/repeat_prop.png" alt="repeat_prop" /></p>
<div class="qa-a-selection">
<p>重复节点和循环节点相同之处是其子节点都是被多次执行。</p>
<div class="entry-content">
<p>不同之处在于，重复节点是指在“一帧内”执行。而对于循环节点，一帧只执行一次。如果同样都是执行10次，Repeat（10）是一帧内把10次执行完，而Loop（10）是10帧才执行完。</p>
</div>
</div>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorrepeat.cpp">behaviortree/nodes/decorators/decoratorrepeat.cpp</a></p>
<h2 id="time"><span class="ez-toc-section" id="Time">时间（Time）节点</span></h2>
<p>时间节点用于在指定的时间内，持续调用其子节点，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/time.png" alt="time" /></p>
<p>时间节点可以配置其属性“时间”，该属性是float或double类型，可以配置一个常量、成员属性或方法的返回值，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/time_prop.png" alt="time" /></p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratortime.cpp">behaviortree/nodes/decorators/decoratortime.cpp</a></p>
<h2 id="frames"><span class="ez-toc-section" id="Frames">帧数（Frames）节点</span></h2>
<p>帧数节点用于在指定的帧数内，持续调用其子节点，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/frames.png" alt="frames" /></p>
<p>帧数节点可以配置其属性“帧数”，该属性是int类型，可以配置一个常量、成员属性或方法的返回值，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/frames_prop.png" alt="frames" /></p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorframes.cpp">behaviortree/nodes/decorators/decoratorframes.cpp</a></p>
<h2 id="countlimit"><span class="ez-toc-section" id="CountLimit">计数限制（CountLimit）节点</span></h2>
<p>计数限制节点不同于循环节点，它在指定的循环次数到达前返回子节点返回的状态，无论成功、失败还是正在执行，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/countlimit.png" alt="countlimit" /></p>
<p>计数限制节点在指定的循环次数到达后不再执行。如果指定的循环次数小于0，则表示无限循环，等同于什么操作都没有，只是执行子节点并且返回子节点的返回值。</p>
<p>此外，计数限制节点上还可以添加中断条件作为重新开始条件，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/countlimit_interupt.png" alt="countlimit" /></p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorcountlimit.cpp">behaviortree/nodes/decorators/decoratorcountlimit.cpp</a></p>
<h2 id="successuntilfailureuntil"><span class="ez-toc-section" id="SuccessUntilFailureUntil">返回成功直到（SuccessUntil）/返回失败直到（FailureUntil）</span></h2>
<p>返回成功直到节点在指定的次数到达前返回成功，指定的次数到达后返回失败。如果指定的次数小于0，则总是返回成功。如下图所示：</p>
<p><img class="aligncenter" src="/img/references/successuntil.png" alt="successuntil" /></p>
<p>返回失败直到节点在指定的次数到达前返回失败，指定的次数到达后返回成功。如果指定的次数小于0，则总是返回失败。如下图所示：</p>
<p><img class="aligncenter" src="/img/references/failureuntil.png" alt="failureuntil" /></p>
<p>具体的执行逻辑可以分别查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorsuccessuntil.cpp">behaviortree/nodes/decorators/decoratorsuccessuntil.cpp</a>和<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/decorators/decoratorfailureuntil.cpp">behaviortree/nodes/decorators/decoratorfailureuntil.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/decorator/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>结束节点</title>
		<link>/end/</link>
					<comments>/end/#respond</comments>
		
		<dc:creator><![CDATA[cainhuang]]></dc:creator>
		<pubDate>Fri, 08 Sep 2017 10:54:30 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=2080</guid>

					<description><![CDATA[结束（End）节点可以使用于行为树执行过程中的强制返回，即终止该行为树的全部执行，整个行为树直接返回当前结束节点所配置的“结束状态”值，如下图所示： 在上图中，<a class="moretag" href="/end/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>结束（End）节点可以使用于行为树执行过程中的强制返回，即终止该行为树的全部执行，整个行为树直接返回当前结束节点所配置的“结束状态”值，如下图所示：</p>
<p id="vgYsFSw"><img class="size-full wp-image-2081 aligncenter" src="/wp-content/uploads/2017/09/img_59b275e8e9919.png" alt="" srcset="/wp-content/uploads/2017/09/img_59b275e8e9919.png 845w, /wp-content/uploads/2017/09/img_59b275e8e9919-300x133.png 300w, /wp-content/uploads/2017/09/img_59b275e8e9919-768x342.png 768w, /wp-content/uploads/2017/09/img_59b275e8e9919-604x270.png 604w" sizes="(max-width: 845px) 100vw, 845px" /></p>
<p>在上图中，当执行到结束节点时，行为树直接返回Success，不再执行下面ID为0的动作节点。</p>
<p>可以为结束节点配置“结束状态”属性，如下图所示：</p>
<p id="FybmXDU"><img class="size-full wp-image-2087 aligncenter" src="/wp-content/uploads/2017/09/img_59b64306bb1cf.png" alt="" srcset="/wp-content/uploads/2017/09/img_59b64306bb1cf.png 446w, /wp-content/uploads/2017/09/img_59b64306bb1cf-300x126.png 300w" sizes="(max-width: 446px) 100vw, 446px" /></p>
<p>上面的“结束状态”可以是一个常量，也可以是成员属性或方法的返回值，表示行为树执行到结束节点时，强制返回“结束状态”所配置的当前值。</p>
<p>注意：只有“结束状态”的当前值是Success或Failure时，行为树才会结束并返回该值；为Invalid或Running时，该结束节点不起作用，行为树接着执行。</p>
<p>此外，还有一个属性“结束外层树”，该属性用于表示在子树中的结束节点返回时，是否需要返回该子树所在的父树。</p>
<p>例如，创建一个带有结束节点的子树subtree1，如下图所示：</p>
<p id="Omcutmo"><img class="size-full wp-image-2088 aligncenter" src="/wp-content/uploads/2017/09/img_59b6438c10cec.png" alt="" srcset="/wp-content/uploads/2017/09/img_59b6438c10cec.png 819w, /wp-content/uploads/2017/09/img_59b6438c10cec-300x137.png 300w, /wp-content/uploads/2017/09/img_59b6438c10cec-768x351.png 768w" sizes="(max-width: 819px) 100vw, 819px" /></p>
<p>调用该子树的父树maintree1如下图所示：</p>
<p id="sHOEmcY"><img class="size-full wp-image-2089 aligncenter" src="/wp-content/uploads/2017/09/img_59b643dc926d1.png" alt="" srcset="/wp-content/uploads/2017/09/img_59b643dc926d1.png 827w, /wp-content/uploads/2017/09/img_59b643dc926d1-300x133.png 300w, /wp-content/uploads/2017/09/img_59b643dc926d1-768x340.png 768w" sizes="(max-width: 827px) 100vw, 827px" /></p>
<p>如果子树subtree1中结束节点的“结束外层树”属性没有勾选，那么在执行父树maintree1的ID为4的子树节点时，会进入子树subtree1中，在该子树中执行到ID为3的结束节点时，会直接返回Success，不再执行ID为2的动作节点。子树subtree1返回后，回到父树maintree1中，由于子树subtree1中的结束节点没有勾选“结束外层树”属性，父树maintree1中ID为5的动作节点会继续得到执行。</p>
<p>但是如果勾选了子树subtree1中结束节点的“结束外层树”属性，则上述的执行过程会有所变化，也即子树subree1返回Success后，父树maintree1也直接返回Success，父树maintree1中ID为5的动作节点不再执行。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/end.cpp">behaviortree/nodes/actions/end.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/end/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>赋值节点</title>
		<link>/assignment/</link>
					<comments>/assignment/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Mon, 11 Apr 2016 09:15:21 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=132</guid>

					<description><![CDATA[赋值（Assignment）节点实现了赋值的操作，可以把右边的值赋值给左侧的参数，如下图所示： 其中，左参数是某个Agent实例的属性，右参数可以是常数、Age<a class="moretag" href="/assignment/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>赋值（Assignment）节点实现了赋值的操作，可以把右边的值赋值给左侧的参数，如下图所示：</p>
<p><img src="/img/references/assignment.png" alt="assignment" /></p>
<p>其中，左参数是某个Agent实例的属性，右参数可以是常数、Agent实例的属性或者方法调用的返回值，如下图所示：</p>
<p><img class="alignnone size-medium wp-image-935" src="/wp-content/uploads/2016/04/无标题-300x70.png" alt="无标题" width="300" height="70" srcset="/wp-content/uploads/2016/04/无标题-300x70.png 300w, /wp-content/uploads/2016/04/无标题.png 498w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<h2>类型转换</h2>
<ul>
<li>3.5.10及以后版本才支持</li>
<li>当属性‘类型转换’没有选中的时候，赋值节点只允许相同的类型进行赋值，也就是说右参数的下拉列表中仅列出与左参数相同类型的参数。</li>
<li>而‘类型转换’选中的时候，赋值节点允许较为宽松的类型。
<ul>
<li>当左参数是数据类型（int，short，byte，float等）的时候，右参数也将是数据类型，不需要完全一致。</li>
<li>当左参数是指针类型（对于C#是引用类型）的时候，右参数将是左参数类型的同类或子类。</li>
</ul>
</li>
</ul>
<h2>其他</h2>
<p>当需要对某个属性做一些加减乘除运算的时候，可以用<a href="/docs/zh/references/compute/">计算节点</a>。</p>
<p>另外，如果需要修改某些其他没有导出的属性，或做一些复杂的计算时，可以通过<a href="/docs/zh/references/action/">动作节点</a>调用相应的函数来实现修改或计算。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/assignment.cpp">behaviortree/nodes/actions/assignment.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/assignment/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>计算节点</title>
		<link>/compute/</link>
					<comments>/compute/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Thu, 12 May 2016 10:14:24 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=234</guid>

					<description><![CDATA[计算（Compute）节点对常数、属性或函数的返回值做加减乘除的运算，把结果赋值给某个属性，如下图所示： 图1 计算节点 其中，左参数是某个Agent实例的属性<a class="moretag" href="/compute/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>计算（Compute）节点对常数、属性或函数的返回值做加减乘除的运算，把结果赋值给某个属性，如下图所示：</p>
<p><img src="/img/references/compute.png" alt="compute" /></p>
<p>图1 计算节点</p>
<p>其中，左参数是某个Agent实例的属性，参数1和参数2可以是常数、Agent实例的属性或者方法调用的返回值，操作符可以是”+, -, *, /”，如下图所示：</p>
<p><img src="/img/references/compute_prop.png" alt="compute" /></p>
<p>图2 计算节点的属性</p>
<p>请注意这些操作的“粒度”过小，大量这种小粒度的操作可能对性能造成影响。</p>
<p>另外，如果需要修改某些其他没有导出的属性，或做一些复杂的计算时，可以通过<a href="/docs/zh/references/action/">动作节点</a>调用相应的函数来实现修改或计算。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/compute.cpp">behaviortree/nodes/actions/compute.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/compute/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>附件</title>
		<link>/attachment/</link>
					<comments>/attachment/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Thu, 12 May 2016 10:10:18 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[事件]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=226</guid>

					<description><![CDATA[附件（Attachments）类型可以附加到相应的节点上，在编辑器中有两类附件：显式附件和隐式附件。 1 显式附件 显式附件包括前置和后置，如下图所示： 可以在<a class="moretag" href="/attachment/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>附件（Attachments）类型可以附加到相应的节点上，在编辑器中有两类附件：显式附件和隐式附件。</p>
<h2 id="section">1 显式附件</h2>
<p>显式附件包括前置和后置，如下图所示：</p>
<p><img src="/img/references/attachment.png" alt="attachment" /></p>
<p>可以在任何一个节点通过鼠标拖拽来添加前置或后置附件，前置往往是作为前提条件（precondition）来使用，而后置往往是当节点结束的时候施加效果（effect）。</p>
<p>前置的属性主要有“联合”、“执行时机”、“左参数”、“操作符”和“右参数”等，如下图所示：</p>
<p><img src="/img/references/preaction_prop.png" alt="attachment" /></p>
<p>其中，“联合”是用于同一个节点的多个前置是“与（and）”还是“或（or）”的运算关系，执行时的逻辑顺序是从上往下依次执行，不管“与”还是“或”。如果“联合”是and<br />
&#8211; 如果有a，b两个前置，则最后的结果是（a and b）。<br />
&#8211; 如果有a，b，c三个前置，则最后的结果是（a and b and c），也即：（（a and b） and c）。如果a是false，b和c还是会计算，没有shortcut的优化。</p>
<p>如果“联合”是or<br />
&#8211; 如果有a，b两个前置，则最后的结果是（a or b）。<br />
&#8211; 如果有a，b，c三个前置，则最后的结果是（a or b or c），也即：（（a or b） or c）。如果a是true，b和c还是会计算，没有shortcut的优化。</p>
<p>“执行时机”分为Enter、Update和Both三种类型：</p>
<ul>
<li>Enter表示进入所在节点时，需要检查该前置。</li>
<li>Update表示所在节点每次更新时，都需要检查该前置。</li>
<li>Both表示不管所在节点是刚进入还是每次更新时，都需要检查该前置。</li>
</ul>
<p>后置的属性主要有“执行时机”、“左参数”、“操作符”和“右参数”等，如下图所示：</p>
<p><img src="/img/references/postaction_prop.png" alt="attachment" /></p>
<p>“执行时机”分为Success、Failure和Both三种类型：</p>
<ul>
<li>Success表示所在节点执行成功后，才需要继续执行该后置。</li>
<li>Failure表示所在节点执行失败后，才需要继续执行该后置。</li>
<li>Both表示不管所在节点执行成功还是失败后，都需要继续执行该后置。</li>
</ul>
<h2 id="section-1">2 隐式附件</h2>
<p>隐式附件主要是指事件这种附件，编辑器中没有单独的事件节点供拖拽来产生，需要通过拖拽另一棵行为树到目标行为树的节点来间接产生该事件附件。</p>
<p>只有根节点是Task的子树才能被拖拽到另一个符合要求的树上生成事件。</p>
<p>请详看文档《<a href="/docs/zh/tutorials/tutorial11_event/">事件处理</a>》。</p>
]]></content:encoded>
					
					<wfw:commentRss>/attachment/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>任务节点</title>
		<link>/task/</link>
					<comments>/task/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:12:05 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[事件]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=260</guid>

					<description><![CDATA[任务节点（Task）用于描述一个接口，该接口的入口参数为当前的行为树提供了局部变量，这些局部变量可以根据需要用于该行为树所有子节点，如下图所示： 图1 任务节点<a class="moretag" href="/task/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>任务节点（Task）用于描述一个接口，该接口的入口参数为当前的行为树提供了局部变量，这些局部变量可以根据需要用于该行为树所有子节点，如下图所示：</p>
<p><img src="/img/references/task.png" alt="task" /></p>
<p>图1 任务节点</p>
<p>注意：任务节点只能作为行为树的第一个子节点存在，在任务节点上可以添加其他子节点。</p>
<p>在任务节点的任务属性中需要选择在类型信息浏览器中创建的事件，如下图所示：</p>
<p><img src="/img/references/task_prop.png" alt="task" /></p>
<p>图2 任务节点的属性</p>
<p>带有任务节点的行为树主要用于事件的处理，请详看文档《<a href="/docs/zh/tutorials/tutorial11_event/">事件处理</a>》。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/htn/task.cpp">htn/task.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/task/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>子树节点</title>
		<link>/subtree/</link>
					<comments>/subtree/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:14:04 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=264</guid>

					<description><![CDATA[子树的介绍 通过子树节点，一个行为树可以作为另一个行为树的子树。作为子树的那个行为树被“调用”。如同一个动作节点一样，子树节点根据子树的执行结果也会返回执行结果<a class="moretag" href="/subtree/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<h2 id="section"><span class="ez-toc-section" id="i">子树的介绍</span></h2>
<p>通过<code class="highlighter-rouge">子树节点</code>，一个行为树可以作为另一个行为树的<code class="highlighter-rouge">子树</code>。作为子树的那个行为树被“调用”。如同一个动作节点一样，<code class="highlighter-rouge">子树</code>节点根据子树的执行结果也会返回执行结果（成功、失败或运行。），其父节点按照自己的控制逻辑来控制接下来的运行。<br />
<img src="/img/references/subtree.png" alt="" /></p>
<h3 id="section-1"><span class="ez-toc-section" id="i-2">递归</span></h3>
<p>一个行为树可以“调用”自己，这么做的时候形成递归，形成递归的时候需要注意不要造成死循环，这可以通过变量的使用来避免。</p>
<p>如下图所示，利用testVar_0来避免死循环：第一次进入的时候testVar_0 == 0，所以可以执行下面的序列，先把testVar_0赋值为1，那么在下面的递归重入的时候由于testVar_0 == 1，所以testVar_0 == 0的条件不满足，所以下面的序列不会进入从而避免了死循环。</p>
<p><img src="/img/overview/reverse.png" alt="" /></p>
<h2 id="section-2"><span class="ez-toc-section" id="i-3">子树节点的属性</span></h2>
<p>当选取子树节点的时候，在属性面板中显示如下图的属性：<br />
<img src="/img/references/subtree_property.png" alt="" /></p>
<ul>
<li><code class="highlighter-rouge">引用文件名</code>，作为被调用的子树的行为树的相对路径。该属性不允许为空，需要是有效的路径。没有提供有效路径会导致报错并且该树不允许被导出。<code class="highlighter-rouge">引用文件名</code>可以是const常量，可以是变量(其值是行为树的相对路径)，或函数（其返回值需要是字符串，是行为树的相对路径）</li>
<li><code class="highlighter-rouge">任务</code>，如果子树的根节点是任务节点，这里会出现该任务，并且允许提供参数。如在最上的图中，8号节点travel(x, ax)，4号节点travel(ay, y)。如果子树的根节点不是任务节点，或者<code class="highlighter-rouge">引用文件名</code>不是常量，<code class="highlighter-rouge">任务</code>属性就是空的。</li>
</ul>
<h2 id="section-3"><span class="ez-toc-section" id="i-4">添加子树节点</span></h2>
<ul>
<li>在编辑器中，可以通过鼠标拖拽一棵行为树到另一棵行为树中生成子树节点，被拖拽的行为树的路径被设置到<code class="highlighter-rouge">引用文件名</code>。需要指出的是，并非任意一个行为树都可以作为另外一个行为树的子树。作为子树的行为树的Agent类型需要是“父树”的Agent类型的子类或同类。</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>
<h2 id="section-4"><span class="ez-toc-section" id="i-5">版本</span></h2>
<p>在3.4.0之前的版本中，子树节点只允许配置常量，只允许使用鼠标拖拽一棵行为树到另一棵行为树中生成子树节点。在3.4.0及以后的版本中，<code class="highlighter-rouge">引用文件名</code>可以是常量，也可以是变量或函数，也就是说3.4.0及以后的版本中，子树节点引用的子树可以是”动态”的。</p>
<div class="section-nav"></div>
]]></content:encoded>
					
					<wfw:commentRss>/subtree/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>选择监测节点</title>
		<link>/selectormonitor/</link>
					<comments>/selectormonitor/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:11:13 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[事件]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=258</guid>

					<description><![CDATA[选择监测节点（SelectorMonitor）和监测分支节点（WithPrecondition）作为对传统行为树的扩展，可以很自然的处理事件和状态的改变，类似于<a class="moretag" href="/selectormonitor/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>选择监测节点（SelectorMonitor）和监测分支节点（WithPrecondition）作为对传统行为树的扩展，可以很自然的处理事件和状态的改变，类似于程序语言中的“switch&#8230;case”语句，如下图所示：</p>
<p id="xojrlZA"><img class="size-full wp-image-2000 aligncenter" src="/wp-content/uploads/2017/04/img_59015d5a54a9a.png" alt="" srcset="/wp-content/uploads/2017/04/img_59015d5a54a9a.png 887w, /wp-content/uploads/2017/04/img_59015d5a54a9a-300x126.png 300w, /wp-content/uploads/2017/04/img_59015d5a54a9a-768x323.png 768w" sizes="(max-width: 887px) 100vw, 887px" /></p>
<ul>
<li>选择监测和监测分支节点只能配对使用，即选择监测节点只能添加监测分支节点作为它的子节点，监测分支节点也只能作为选择监测节点的子节点被添加。</li>
<li>监测分支节点有条件分支子树和动作分支子树。只有条件分支子树返回成功的时候，动作分支子树才能够被执行。</li>
<li>选择监测节点是一个动态的选择节点，与选择节点（Selector）相同的是，它选择第一个返回成功的子节点，但不同的是，它不是只选择一次，而是每次执行时都对其子节点重新评估后再进行选择。</li>
</ul>
<p>默认情况下，上一次得到执行的动作分支，如果在下一次其条件分支也返回成功，那么这个动作分支会继续执行上次返回正在运行的节点。例如，假设上图中上一次执行行为树的时候，ID为13的条件节点返回成功，并且已经执行到ID为9的动作节点（这时ID为4的动作节点已返回成功，而ID为9的动作节点返回正在运行）。那么，当下一次执行该选择检测节点时，如果发现ID为13的条件节点还是返回成功，ID为9的动作节点就会直接得到执行，而不是先执行ID为4的动作节点。</p>
<p>但有的时候，可能需要在条件分支再次得到满足时，其动作分支需要重新执行，而不是默认情况下的从上次返回正在执行的节点继续执行。例如，对于上面的例子，当ID为13的条件节点再次返回成功时，需要重新执行其动作分支，即重新开始执行ID为4的动作节点。这时候，需要勾选上选择检测节点的属性“重置子节点”，如下图所示：</p>
<p id="TIymLqP"><img class="size-full wp-image-2001 aligncenter" src="/wp-content/uploads/2017/04/img_59016087886d5.png" alt="" srcset="/wp-content/uploads/2017/04/img_59016087886d5.png 476w, /wp-content/uploads/2017/04/img_59016087886d5-300x60.png 300w" sizes="(max-width: 476px) 100vw, 476px" /></p>
<p>勾选该属性后，选择检测节点每次执行时，都会从头开始执行其动作分支。</p>
<p>选择检测节点的实现很像并行节点，每帧都要重新执行所有的子树，大量使用的时候请注意其性能。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/selectorloop.cpp">behaviortree/nodes/composites/selectorloop.cpp</a></p>
<p>另外，执行行为树的过程中，当状态、条件发生变化或发生事件（Event）时如何响应或打断当前的执行是个重要的问题。</p>
<p>目前behaviac组件支持三种方式来处理状态变化或事件发生：并行节点、选择监测节点、事件附件等。简而言之，并行和选择监测节点的工作方式是采用“轮询”的方式，每次执行时需要重新评估所有子节点，而不是像其他节点会保留上一次正在执行的子节点以便在下一次执行时继续执行。事件附件是在游戏逻辑（程序端）发出事件时，才按需得到响应。</p>
<p>请详看文档《<a href="/docs/zh/tutorials/tutorial11_event/">事件处理</a>》。</p>
]]></content:encoded>
					
					<wfw:commentRss>/selectormonitor/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>条件执行节点</title>
		<link>/ifelse/</link>
					<comments>/ifelse/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:10:22 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=256</guid>

					<description><![CDATA[条件执行节点（IfElse）是behaviac组件的一个扩展或快捷方式。 条件执行节点必须要有3个子节点，第一个子节点是条件分支，第二个子节点是“真时执行”分支<a class="moretag" href="/ifelse/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>条件执行节点（IfElse）是behaviac组件的一个扩展或快捷方式。</p>
<p>条件执行节点必须要有3个子节点，第一个子节点是条件分支，第二个子节点是“真时执行”分支，第三个子节点是“假时执行”分支。如果条件为真，那么执行“真时执行”分支；否则，执行“假时执行”分支。</p>
<p>而条件执行节点的执行结果则根据具体执行分支的执行结果来决定，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/ifelse.png" alt="ifelse" /></p>
<p>如果不使用条件执行节点，完全可以用序列（Sequence）和选择（Selector）节点来实现相同的功能，只不过没有条件执行节点简洁。</p>
<p>另外，条件执行节点的“条件”分支，还可以挂上动作节点甚至是一棵子树。比如挂上动作节点时，如果该动作节点返回Running，则条件执行节点也返回Running，并且该条件一直持续执行，直到动作节点返回Success或Failure，则继续相应的执行“真时执行”或“假时执行”分支。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/ifelse.cpp">behaviortree/nodes/composites/ifelse.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/ifelse/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>随机序列节点</title>
		<link>/sequencestochastic/</link>
					<comments>/sequencestochastic/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:09:28 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=254</guid>

					<description><![CDATA[类似序列（Sequence）节点，随机序列（SequenceStochastic）节点也是从子节点中顺序执行，但不像序列节点每次都是按照排列的先后顺序，随机序列<a class="moretag" href="/sequencestochastic/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>类似序列（Sequence）节点，随机序列（SequenceStochastic）节点也是从子节点中顺序执行，但不像序列节点每次都是按照排列的先后顺序，随机序列节点每次执行子节点时随机的决定其执行顺序，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/sequencestochastic.png" alt="sequencestochastic" /></p>
<p>例如，序列节点和随机序列节点都有A、B、C、D这四个子节点。对于序列节点，每次都是按A、B、C、D的顺序依次执行；而对于随机序列节点，有时按A、B、C、D的顺序执行，有时按B、A、D、C的顺序执行，又有时按A、C、D、B的顺序执行，等等。</p>
<p>与随机选择节点相同的是，随机序列节点也有随机数生成器可以配置，该随机数生成器是一个返回值为0.0到1.0之间的float类型的函数，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/sequencestochastic_prop.png" alt="sequencestochastic" /></p>
<p>该随机数生成器一般设为空即可，表示采用系统的缺省实现，也可以使用自己提供的函数。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/sequencestochastic.cpp">behaviortree/nodes/composites/sequencestochastic.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/sequencestochastic/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>随机选择节点</title>
		<link>/selectorstochastic/</link>
					<comments>/selectorstochastic/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:08:39 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=252</guid>

					<description><![CDATA[类似选择（Selector）节点，随机选择（SelectorStochastic）节点也是从子节点中选择执行一个，但不像选择节点每次都是按照排列的先后顺序选择，<a class="moretag" href="/selectorstochastic/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>类似选择（Selector）节点，随机选择（SelectorStochastic）节点也是从子节点中选择执行一个，但不像选择节点每次都是按照排列的先后顺序选择，随机选择节点每次选择的时候随机的决定执行顺序，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/selectorstochastic.png" alt="selectorstochastic" /></p>
<p>例如，选择节点和随机选择节点都有A、B、C、D这四个子节点。对于选择节点，每次都是顺序的按A、B、C、D的顺序选择；而对于随机选择节点，有时按A、B、C、D的顺序选择，有时按B、A、D、C的顺序选择，又有时按A、C、D、B的顺序选择，等等。</p>
<p>随机选择节点有随机数生成器可以配置，该随机数生成器是一个返回值为0.0到1.0之间的float类型的函数，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/selectorstochastic_prop.png" alt="selectorstochastic" /></p>
<p>该随机数生成器一般设为空即可，表示采用系统的缺省实现，也可以使用自己提供的函数。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/selectorstochastic.cpp">behaviortree/nodes/composites/selectorstochastic.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/selectorstochastic/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>概率选择节点</title>
		<link>/selectorprobability/</link>
					<comments>/selectorprobability/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:07:34 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=250</guid>

					<description><![CDATA[类似选择（Selector）节点，概率选择（SelectorProbability）节点也是从子节点中选择执行一个，但不像选择节点每次都是按照排列的先后顺序选择<a class="moretag" href="/selectorprobability/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>类似选择（Selector）节点，概率选择（SelectorProbability）节点也是从子节点中选择执行一个，但不像选择节点每次都是按照排列的先后顺序选择，概率选择节点每次选择的时候根据子节点的“概率权值”进行选择，权值越大，被选到的机会越大，权值为0，则其分支不会被执行，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/selectorprobability.png" alt="selectorprobability" /></p>
<p>注意：选择节点是按照从上到下的顺序依次执行子节点，一直到第一个返回成功的那个子节点则返回成功，或者如果所有子节点都返回失败则返回失败。</p>
<p>而概率选择节点则是根据概率“直接”选择并执行某个子节点，无论其返回成功还是失败，概率选择节点也将返回同样的结果。如果该子节点返回失败，概率选择也返回失败，它不会像选择节点那样会继续执行接下来的子节点。</p>
<p>概率选择节点有随机数生成器可以配置，该随机数生成器是一个返回值为0.0到1.0之间的float类型的函数，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/selectorprobability_prop.png" alt="selectorprobability" /></p>
<p>该随机数生成器一般设为空即可，表示采用系统的缺省实现，也可以使用自己提供的函数。</p>
<p>概率选择节点的子节点只能是“权值”的子节点，在添加子节点时，该权值节点会被系统自动添加。所有权值子节点的相加之和不需要是100，执行时会进行归一化操作，子节点的概率是该子节点的权值/总和。</p>
<p>概率选择节点的选择算法是基于概率区间的，比如上图中的3个子节点的权值分别是20、30、50，归一化后的概率分别是0.2、0.3、0.5，那么对应的概率区间分别是[0.0, 0.2)、[0.2, 0.5)、[0.5, 1.0)。概率选择节点的随机数生成器随机产生一个[0.0, 1.0)之间的随机数，看这个随机数落在哪个区间，则执行第几个子节点。例如，随机数为0.45，落在第二个区间[0.2, 0.5)，则选择执行第二个子节点。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/composites/selectorprobability.cpp">behaviortree/nodes/composites/selectorprobability.cpp</a></p>
<div class="section-nav"></div>
]]></content:encoded>
					
					<wfw:commentRss>/selectorprobability/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>或节点</title>
		<link>/or/</link>
					<comments>/or/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:03:49 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=244</guid>

					<description><![CDATA[或（Or）节点接受两个以上的条件子节点，执行逻辑”或（ ）”操作，如下图所示： 图1 或节点 只要有一个条件子节点的返回值为成功，或节点则返回成功。所有条件子节<a class="moretag" href="/or/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>或（Or）节点接受两个以上的条件子节点，执行逻辑”或（ ）”操作，如下图所示：<img src="/img/references/or.png" alt="or" /></p>
<p>图1 或节点</p>
<p>只要有一个条件子节点的返回值为成功，或节点则返回成功。所有条件子节点都返回为失败，或节点则返回失败。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/conditions/or.cpp">behaviortree/nodes/conditions/or.cpp</a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/or/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>与节点</title>
		<link>/and/</link>
					<comments>/and/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Mon, 11 Apr 2016 09:11:22 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=130</guid>

					<description><![CDATA[与（And）节点接受两个以上的条件子节点，执行逻辑”与（&#38;&#38;）”操作，如下图所示： 图1 与节点 只要有一个条件子节点的返回值为失败，与节点则返<a class="moretag" href="/and/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>与（And）节点接受两个以上的条件子节点，执行逻辑”与（&amp;&amp;）”操作，如下图所示：</p>
<p><img src="/img/references/and.png" alt="and" /></p>
<p>图1 与节点</p>
<p>只要有一个条件子节点的返回值为失败，与节点则返回失败。所有条件子节点都返回为成功，与节点则返回成功。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/conditions/and.cpp">behaviortree/nodes/conditions/and.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/and/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>等待节点</title>
		<link>/wait/</link>
					<comments>/wait/#comments</comments>
		
		<dc:creator><![CDATA[jonygli]]></dc:creator>
		<pubDate>Mon, 06 Jun 2016 10:11:17 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=460</guid>

					<description><![CDATA[等待（Wait）节点在指定的数值内（单位根据自己的使用场景来定）持续保持为运行（Running）状态，数值到达之后则返回成功，如下图所示： 需要配置“持续时间”<a class="moretag" href="/wait/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>等待（Wait）节点在指定的数值内（单位根据自己的使用场景来定）持续保持为运行（Running）状态，数值到达之后则返回成功，如下图所示：</p>
<p><img class="aligncenter" src="/img/references/wait.png" alt="wait" /></p>
<p>需要配置“持续时间”，可以是常数、属性或方法的返回值（支持double和int类型），如下图所示：</p>
<p><img class="aligncenter" src="/img/references/wait_prop.png" alt="wait" /></p>
<p>在工作区配置窗口中，可以勾选左下角的“使用整数值”来表示是否使用整数值，如下图所示：</p>
<p><img class="size-full wp-image-1163 aligncenter" src="/wp-content/uploads/2016/06/edit_workspace-1.png" alt="edit_workspace" width="587" height="272" srcset="/wp-content/uploads/2016/06/edit_workspace-1.png 587w, /wp-content/uploads/2016/06/edit_workspace-1-300x139.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<p>如果勾选了“使用整数值”选项，那么在导出代码文件behaviac_agent_meta.cpp中，会自动生成Workspace::GetInstance()-&gt;SetUseIntValue(true)。</p>
<p>等待节点的更新逻辑是：</p>
<div class="highlighter-rouge">
<pre class="highlight"><code>bool bUseIntValue = Workspace::GetInstance()-&gt;GetUseIntValue();

if (bUseIntValue)
{
    long long time = Workspace::GetInstance()-&gt;GetIntValueSinceStartup();

    if (time - this-&gt;m_intStart &gt;= this-&gt;m_intTime)
    {
        return BT_SUCCESS;
    }
}
else
{
    double time = Workspace::GetInstance()-&gt;GetDoubleValueSinceStartup();

    if (time - this-&gt;m_start &gt;= this-&gt;m_time)
    {
        return BT_SUCCESS;
    }
}
</code></pre>
</div>
<p>因此，只有保证Workspace::GetInstance()-&gt;GetIntValueSinceStartup()或Workspace::GetInstance()-&gt;GetDoubleValueSinceStartup()正确的返回从游戏启动到现在的总时间，等待节点才能正确工作。</p>
<p>如果勾选了“使用整数值”选项，那么Workspace::GetInstance()-&gt;GetUseIntValue()将返回true，并且该总数值需要通过Workspace::GetInstance()-&gt;SetIntValueSinceStartup(long long value)设置，可以在自己的游戏更新函数中调用该函数。</p>
<p>如果没有勾选“使用整数值”选项，那么Workspace::GetInstance()-&gt;GetUseIntValue()将返回false。该总时间需要通过Workspace::GetInstance()-&gt;SetDoubleValueSinceStartup(double value)设置，可以在自己的游戏更新函数中调用该函数。</p>
<p>注意：在C#代码中相应的接口需改为Workspace.Instance.IntValueSinceStartup或Workspace.Instance.DoubleValueSinceStartup，默认实现方式是返回Unity的系统时间Time.realtimeSinceStartup，一般情况无需自己重新实现，直接使用即可，不用类似C++的接口每帧更新时调用Workspace.Instance.IntValueSinceStartup或Workspace.Instance.DoubleValueSinceStartup为其赋值。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/wait.cpp">behaviortree/nodes/actions/wait.cpp</a></p>
<div class="section-nav"></div>
]]></content:encoded>
					
					<wfw:commentRss>/wait/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>等待帧数节点</title>
		<link>/waitframes/</link>
					<comments>/waitframes/#respond</comments>
		
		<dc:creator><![CDATA[jonygli]]></dc:creator>
		<pubDate>Mon, 06 Jun 2016 10:14:25 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=463</guid>

					<description><![CDATA[//www 图1 等待帧数节点 需要配置“帧数”，可以是常数、属性或方法的返回值（必须是int类型），如下图所示： 图2 等待帧数节点的属性 等待帧数节点的更新<a class="moretag" href="/waitframes/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>//www</p>
<p><img src="/img/references/waitframes.png" alt="waitframes" /></p>
<p>图1 等待帧数节点</p>
<p>需要配置“帧数”，可以是常数、属性或方法的返回值（必须是int类型），如下图所示：</p>
<p><img src="/img/references/waitframes_prop.png" alt="waitframes" /></p>
<p>图2 等待帧数节点的属性</p>
<p>等待帧数节点的更新逻辑是:</p>
<div class="highlighter-rouge">
<pre class="highlight"><code><span class="k">if</span> <span class="p">(</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">GetFrameSinceStartup</span><span class="p">()</span> <span class="o">-</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">m_start</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&gt;=</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">m_frames</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">return</span> <span class="n">BT_SUCCESS</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>
<p>因此，只有保证Workspace::GetInstance()-&gt;GetFrameSinceStartup()正确的返回从游戏启动到当前的总帧数，等待帧数节点才能正确工作。</p>
<p>该总帧数需要通过Workspace::GetInstance()-&gt;SetFrameSinceStartup()设置，可以在自己的游戏更新函数中调用该函数。</p>
<p>注意：在C#代码中相应的接口需改为Workspace.Instance.FrameSinceStartup，默认实现方式是返回Unity的当前系统帧数Time.frameCount，一般情况无需自己重新实现，直接使用即可，不用类似以上C++的接口方式每帧更新时再额外调用Workspace.Instance.FrameSinceStartup为其赋值。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/waitframes.cpp">behaviortree/nodes/actions/waitframes.cpp</a></p>
<div class="section-nav"></div>
]]></content:encoded>
					
					<wfw:commentRss>/waitframes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>状态机</title>
		<link>/fsm/</link>
					<comments>/fsm/#respond</comments>
		
		<dc:creator><![CDATA[jonygli]]></dc:creator>
		<pubDate>Fri, 13 May 2016 02:12:55 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=262</guid>

					<description><![CDATA[简介 behaviac组件不仅支持行为树，也支持有限状态机（FSM），并且支持行为树跟状态机的相互嵌套调用。 behaviac组件中的状态机主要用到了状态（St<a class="moretag" href="/fsm/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<h2><span class="ez-toc-section" id="i">简介</span></h2>
<p>behaviac组件不仅支持行为树，也支持有限状态机（FSM），并且支持行为树跟状态机的相互嵌套调用。</p>
<p>behaviac组件中的状态机主要用到了状态（State）、等待状态（WaitState）和等待帧数状态（WaitFramesState）三种节点，以及条件转换（Transition）和总是转换（AlwaysTransition）两种附件，如下图所示：</p>
<p><img src="/img/references/fsm_nodes.png" alt="fsm_nodes" /></p>
<p>图1 状态机相关节点和附件</p>
<h2 id="section"><span class="ez-toc-section" id="i-2">状态节点</span></h2>
<p>状态节点（State）是状态机中的基本组成部分之一，可以在状态节点上添加前置、后置以及转换等附件，如下图所示：</p>
<p><img src="/img/references/state.png" alt="state" /></p>
<p>图2 状态节点</p>
<ul>
<li>在状态节点上添加的前置：表明进入该状态节点时，需要执行的操作。</li>
<li>在状态节点上添加的后置：表明退出该状态节点时，需要执行的操作。</li>
<li>在状态节点上添加的转换：表明满足该转换所表示的条件时，由当前状态切换到转换所指向的下一个状态。</li>
</ul>
<p>如下图所示，可以编辑状态节点的相关属性：</p>
<p><img src="/img/references/state_prop.png" alt="state" /></p>
<p>图3 状态节点的属性</p>
<ul>
<li>名字：为状态节点指定一个有意义的名字，以便区分其他状态节点。</li>
<li>方法：表示该状态节点需要执行的操作。</li>
<li>结束状态：如果勾选，表示该状态作为结束状态，即在执行完该状态节点之后，整个状态机也直接结束。该节点形状也将显示为RoundRectangle，以示区别。</li>
</ul>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/fsm/fsmstate.cpp">fsm/fsmstate.cpp</a></p>
<h2 id="section-1"><span class="ez-toc-section" id="i-3">等待状态节点</span></h2>
<p>等待状态节点（WaitState）是一种特殊的状态节点，可以在状态节点上添加前置、后置以及等待转换等附件，如下图所示：</p>
<p><img src="/img/references/waitstate.png" alt="waitstate" /></p>
<p>图4 等待状态节点</p>
<p>添加等待状态节点时，会自动的生成唯一的等待转换附件，不接受添加其他类型的转换附件。</p>
<p>如下图所示，可以编辑等待状态节点的相关属性：</p>
<p><img src="/img/references/waitstate_prop.png" alt="waitstate" /></p>
<p>图5 等待状态节点的属性</p>
<p>相比状态节点的属性，等待状态节点少了“方法”属性，但多出了一个“持续时间”属性，用来指定需要等待多长时间，可以是常数、属性或方法的返回值。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/fsm/waitstate.cpp">fsm/waitstate.cpp</a></p>
<h2 id="section-2"><span class="ez-toc-section" id="i-4">等待帧数状态节点</span></h2>
<p>等待帧数状态节点（WaitFramesState）也是一种特殊的状态节点，可以在状态节点上添加前置、后置以及等待转换等附件，如下图所示：</p>
<p><img src="/img/references/waitframesstate.png" alt="waitframesstate" /></p>
<p>图6 等待帧数状态节点</p>
<p>添加等待帧数状态节点时，会自动的生成唯一的等待转换附件，不接受添加其他类型的转换附件。</p>
<p>如下图所示，可以编辑等待帧数状态节点的相关属性：</p>
<p><img src="/img/references/waitframesstate_prop.png" alt="waitframesstate" /></p>
<p>图7 等待帧数状态节点的属性</p>
<p>相比状态节点的属性，等待帧数状态节点少了“方法”属性，但多出了一个“帧数”属性，用来指定需要等待多少帧数，可以是常数、属性或方法的返回值。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/fsm/waitframesstate.cpp">fsm/waitframesstate.cpp</a></p>
<h2 id="section-3"><span class="ez-toc-section" id="i-5">条件转换附件</span></h2>
<p>转换附件（Transition）是状态机中的基本组成部分之一，它表示一个条件，当这个条件满足时，由所在的状态切换到另一个状态，如下图所示：</p>
<p><img src="/img/references/transition.png" alt="transition" /></p>
<p>图8 转换附件</p>
<p>如下图所示，类似条件节点来编辑转换附件的相关属性：</p>
<p><img src="/img/references/transition_prop.png" alt="transition" /></p>
<p>图9 转换附件的属性</p>
<p>此外，在上图中有个“效果”的属性，是转换附件执行完之后需要执行的额外操作。</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/fsm/startcondition.cpp">fsm/startcondition.cpp</a></p>
<h2 id="section-4"><span class="ez-toc-section" id="i-6">状态转换附件</span></h2>
<p>状态转换附件（StatusTransition）是一种特殊的转换附件，根据它的配置，转换时机会有不同：</p>
<ol>
<li>总跳转，表示无条件从所在的状态切换到另一个状态，如下图所示</li>
<li>成功时，表示当所在节点是子树并且成功的时候转换</li>
<li>失败时，表示当所在节点是子树并且失败的时候转换</li>
<li>结束时，表示当所在节点是子树并且结束（成功或失败）的时候转换</li>
</ol>
<p><img src="/img/references/alwaystransition.png" alt="alwaystransition" /></p>
<p>图10 状态转换附件</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/fsm/alwaystransition.cpp">fsm/alwaystransition.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/fsm/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>空操作节点</title>
		<link>/noop/</link>
					<comments>/noop/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 13 May 2016 01:59:14 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<guid isPermaLink="false">/?p=238</guid>

					<description><![CDATA[空操作（Noop）节点只是作为占位，仅执行一次就返回成功，如下图所示： 图1 空节点 具体的执行逻辑可以查看behaviortree/nodes/actions<a class="moretag" href="/noop/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>空操作（Noop）节点只是作为占位，仅执行一次就返回成功，如下图所示：</p>
<p><img src="/img/references/noop.png" alt="noop" /></p>
<p>图1 空节点</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/noop.cpp">behaviortree/nodes/actions/noop.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/noop/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>等待信号节点</title>
		<link>/waitforsignal/</link>
					<comments>/waitforsignal/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Mon, 11 Apr 2016 09:17:30 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<category><![CDATA[节点]]></category>
		<guid isPermaLink="false">/?p=136</guid>

					<description><![CDATA[等待信号（WaitforSignal）节点模拟了等待某个条件的“阻塞”过程。 等待信号节点返回Running，直到它上面附加的条件是true的时候： 如果有子节<a class="moretag" href="/waitforsignal/">Read More...</a>]]></description>
										<content:encoded><![CDATA[<p>等待信号（WaitforSignal）节点模拟了等待某个条件的“阻塞”过程。</p>
<p>等待信号节点返回Running，直到它上面附加的条件是true的时候：</p>
<ul>
<li>如果有子节点，则执行其子节点，并当子节点结束时，返回该子节点的返回值。</li>
<li>如果没有子节点，则直接返回成功。</li>
</ul>
<p>在图1中，该等待信号节点一直“阻塞”直到它上面附加的条件是true的时候才结束“阻塞”，从而继续序列节点中后面的节点：</p>
<p><img src="/img/references/waitforsignal.png" alt="waitforsignal" /></p>
<p>图1 不带子节点的等待信号节点</p>
<p>而在图2中，则是在该等待信号节点上附加的条件是true的时候，结束“阻塞”而执行其子节点。</p>
<p><img src="/img/references/waitforsignal2.png" alt="waitforsignal" /></p>
<p>图2 带子节点的等待信号节点</p>
<p>具体的执行逻辑可以查看<a href="https://github.com/Tencent/behaviac/blob/master/src/behaviortree/nodes/actions/waitforsignal.cpp">behaviortree/nodes/actions/waitforsignal.cpp</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/waitforsignal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>密码保护：web editor 中角色属性说明</title>
		<link>/web-editor-%e4%b8%ad%e8%a7%92%e8%89%b2%e5%b1%9e%e6%80%a7%e8%af%b4%e6%98%8e/</link>
					<comments>/web-editor-%e4%b8%ad%e8%a7%92%e8%89%b2%e5%b1%9e%e6%80%a7%e8%af%b4%e6%98%8e/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 28 Apr 2017 06:52:40 +0000</pubDate>
				<category><![CDATA[手册]]></category>
		<guid isPermaLink="false">/?p=2010</guid>

					<description><![CDATA[无法提供摘要。这是一篇受保护的文章。]]></description>
										<content:encoded><![CDATA[<form action="/wp-login.php?action=postpass" class="post-password-form" method="post">
<p>这是一篇受密码保护的文章，您需要提供访问密码：</p>
<p><label for="pwbox-2010">密码： <input name="post_password" id="pwbox-2010" type="password" size="20" /></label> <input type="submit" name="Submit" value="提交" /></p>
</form>
]]></content:encoded>
					
					<wfw:commentRss>/web-editor-%e4%b8%ad%e8%a7%92%e8%89%b2%e5%b1%9e%e6%80%a7%e8%af%b4%e6%98%8e/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
