User Tools

Site Tools


dragengine:modules:dragonscript:behaviortrees

Start Page » Game Development with the Drag[en]gine » Behavior Tree File Format

Behavior Trees

Behavior trees are structured graphics describing the AI logic using a tree of rules. The behavior tree is at all times located at one of the rules in the tree. During each simulation step (typically during frame update) the behavior tree moves along the tree until an rule returns either BTResult.running . The behavior tree keeps on running the active rule each simulation step until the rule either returns BTResult.success or BTResult.failure. The AI logic is formed by the logic behind each rule.

Each can also have one or more conditions assigned. Before each run of the rule the conditions are evaluated. If any of the conditions evaluates to false the rule fails. Only the conditions of the active rule are evaluated. The conditions of the parent rule are only evaluated if the active node returns anything else but BTResult.running. In this case the behavior tree wants to move to the next action. To do this the parent rule is run which then automatically evaluates the parent rule conditions.

Conditions can be paramtrized by adding one or more parameters to the rule. The conditions define themselves which parameters they understand and how they react to them. The name of parameters is free but it is recommended to use a naming scheme like this: <source>.<parameter>. This groups parameters and reduces the chance of name conflicts. This is especially important since parameters are also reused for action rules. And while actions already define the source part rather well for conditions this is unknown.

The following rules can be used:

Action

This is the main working rule connecting game logic to the behavior tree. BTAction subclasses are created by the game developer and added to the behavior tree. If the rule is run the action is looked up and run. The return value of the action becomes the return value of the rule.

For performance reasons the action is looked up once then stored in the rule. This is correct behavior as long as the rules are not changed at run-time. If you need changing actions at run-time implement a BTAction forwarding to the desired BTAction. This way the cached action stays valid while the actual BTAction called inside can change. This is though an elaborate situation. Usually actions are added to the behavior tree once and then never change.

If the named action is not found the rule fails with BTResult.failure.

There exists convenience implementations of the BTAction interface linking to action sources present in the game engine:

Script ClassDescription
BTActionParameterTableUpdates the value of a ParameterTree entry.
BTActionTriggerFire or reset a trigger target.
BTActionSendGlobalEventSend a global even using GlobalEvents class, typically BaseGameApp.getApp().getGlobalEvents().
BTBlockAction

Action running a script block like this:

new BTBlockAction(block BTContext context, Dictionary parameters
  // do something
  return BTResult.running // or .success or .failure
end)

This allows to quickly add actions without needing to write a new script class.

Actions can be paramtrized by adding one or more parameters to the rule. The actions define themselves which parameters they understand and how they react to them. The name of parameters is free but it is recommended to use a naming scheme like this: <source>.<parameter>. This groups parameters and reduces the chance of name conflicts. This is especially important since parameters are also reused for rule conditions. And while actions already define the source part rather well for conditions this is unknown.

Sequence

Runs all actions in sequence. Returns BTResult.success if all actions returned BTResult.success . If an action return BTResult.failure processing of the rule stops and BTResult.failure is returned. If no actions are present BTResult.failure is returned.

If looping is set to true the sequence restarts at the beginning if all actions returns BTResult.success . This allows to keep looping a sequence until the first time any action returns BTResult.failure .

Choice

Runs all actions in sequence. Returns BTResult.failure if all actions returned BTResult.failure . If an action returns BTResult.success processing of the rule stops and BTResult.success is returned. If no actions are present BTResult.failure is returned.

If looping is set to true the choice restarts at the beginning if the first action returns BTResult.success . This allows to keep looping a choice until the first time all actions return BTResult.failure .

Success

Returns always BTResult.success unless a rule condition evaluates to false.

The main use for this rule is to test rule conditions without needing to attach them to some other rule.

Failure

Returns always BTResult.failure.

The main use for this rule is to fail a sequence rule by placing this last.

Running

Returns always BTResult.running unless a rule condition evaluates to false.

The main use for this rule is to force waiting until a rule conditions fails.

File Format (*.debtree)

The behavior tree file format is recognized by the LoadBehaviorTree script class. The file is an XML file with a simple structure to define a behavior tree using XML.

behaviorTreeactionsequencechoicesuccessfailurerunningsubtree  stringactionparameter  stringcondition  stringconditionMode  enumsequenceparameter  stringcondition  stringconditionMode  enumactionsequencechoicesuccessfailurerunningsubtree  stringchoiceparameter  stringcondition  stringconditionMode  enumactionsequencechoicesuccessfailurerunningsubtree  stringsuccessparameter  stringcondition  stringconditionMode  enumfailureparameter  stringcondition  stringconditionMode  enumrunningparameter  stringcondition  stringconditionMode  enum

Tags

behaviorTree

TagDescriptionOccuranceDefault
actionAdd action rule0..N-
sequenceAdd sequence rule0..N-
choiceAdd choice rule0..N-
successAdd success rule0..N-
failureAdd failure rule0..N-
runningAdd running rule0..N-
subtreeLoad behavior tree using path from tag text content. Subtree is added to the behavior tree as a sequence rule containing the loaded behavior tree0..N-

action

Adds an action rule.

AttributeDescriptionOccuranceDefault
nameName of action to run.Required-
TagDescriptionOccuranceDefault
parameter

Add parameter. Parameter value is text content of node which can be empty. Attributes:

  • name: Name of parameter. Required.
0..N-
conditionAdd condition. Condition name is text content of node0..N-
conditionMode

How conditions are evaluated. Valid values:

  • allTrue: All conditions have to evaluate to true.
  • anyTrue: At least one condition has to evaluate to true.
  • anyFalse: At least one condition has to evaluate to false.
  • allFalse: All conditions have to evaluate to false.
0..1allTrue

sequence

Adds a sequence rule.

AttributeDescriptionOccuranceDefault
loopLoop sequence.Optionalfalse
doNotFailIf sequence fails return BTResult.success. Useful to optional sequences running as many rules in a sequence as possible without failing the parent rule.Optionalfalse
TagDescriptionOccuranceDefault
parameter

Add parameter. Parameter value is text content of node which can be empty. Attributes:

  • name: Name of parameter. Required.
0..N-
conditionAdd condition. Condition name is text content of node0..N-
conditionMode

How conditions are evaluated. Valid values:

  • allTrue: All conditions have to evaluate to true.
  • anyTrue: At least one condition has to evaluate to true.
  • anyFalse: At least one condition has to evaluate to false.
  • allFalse: All conditions have to evaluate to false.
0..1allTrue
actionAdd action rule0..N-
sequenceAdd sequence rule0..N-
choiceAdd choice rule0..N-
successAdd success rule0..N-
failureAdd failure rule0..N-
runningAdd running rule0..N-
subtreeLoad behavior tree using path from tag text content. Subtree is added to the behavior tree as a sequence rule containing the loaded behavior tree0..N-

choice

Adds a choice rule.

AttributeDescriptionOccuranceDefault
loopLoop choice.Optionalfalse
doNotFailIf choice fails return BTResult.success. Useful for optional choices there failing the choice should not fail the parent rule.Optionalfalse
TagDescriptionOccuranceDefault
parameter

Add parameter. Parameter value is text content of node which can be empty. Attributes:

  • name: Name of parameter. Required.
0..N-
conditionAdd condition. Condition name is text content of node0..N-
conditionMode

How conditions are evaluated. Valid values:

  • allTrue: All conditions have to evaluate to true.
  • anyTrue: At least one condition has to evaluate to true.
  • anyFalse: At least one condition has to evaluate to false.
  • allFalse: All conditions have to evaluate to false.
0..1allTrue
actionAdd action rule0..N-
sequenceAdd sequence rule0..N-
choiceAdd choice rule0..N-
successAdd success rule0..N-
failureAdd failure rule0..N-
runningAdd running rule0..N-
subtreeLoad behavior tree using path from tag text content. Subtree is added to the behavior tree as a sequence rule containing the loaded behavior tree0..N-

success

Adds a success rule.

TagDescriptionOccuranceDefault
parameter

Add parameter. Parameter value is text content of node which can be empty. Attributes:

  • name: Name of parameter. Required.
0..N-
conditionAdd condition. Condition name is text content of node0..N-
conditionMode

How conditions are evaluated. Valid values:

  • allTrue: All conditions have to evaluate to true.
  • anyTrue: At least one condition has to evaluate to true.
  • anyFalse: At least one condition has to evaluate to false.
  • allFalse: All conditions have to evaluate to false.
0..1allTrue

failure

Adds a failure rule.

TagDescriptionOccuranceDefault
parameter

Add parameter. Parameter value is text content of node which can be empty. Attributes:

  • name: Name of parameter. Required.
0..N-
conditionAdd condition. Condition name is text content of node0..N-
conditionMode

How conditions are evaluated. Valid values:

  • allTrue: All conditions have to evaluate to true.
  • anyTrue: At least one condition has to evaluate to true.
  • anyFalse: At least one condition has to evaluate to false.
  • allFalse: All conditions have to evaluate to false.
0..1allTrue

running

Adds a running rule.

TagDescriptionOccuranceDefault
parameter

Add parameter. Parameter value is text content of node which can be empty. Attributes:

  • name: Name of parameter. Required.
0..N-
conditionAdd condition. Condition name is text content of node0..N-
conditionMode

How conditions are evaluated. Valid values:

  • allTrue: All conditions have to evaluate to true.
  • anyTrue: At least one condition has to evaluate to true.
  • anyFalse: At least one condition has to evaluate to false.
  • allFalse: All conditions have to evaluate to false.
0..1allTrue

Examples

Example from the ExampleApp. A simple behavior tree making the actor wander around and if the player gets close tries to stay away from him. If the player is moving fast the actor gets jumpy.

This uses the basic behavior tree system from the game engine with some ready made actions.

<?xml version='1.0' encoding='ISO-8859-1'?>
<behaviorTree>
	<!--
	The basic AI loop. For this example we use a choice with all supported
	behaviors. This could be also done differently but avoids the need to
	use "success" rules to make a choice always succeed if no of the supported
	behaviors applies.
 
	It is possible to add the loop="true" attribute. This would cause the
	root rule to be looping. The difference is subtle but potentially
	problematic. If the rule ends with a success state and looping is set
	to true then the rule will start again from the beginning. As you can
	imagine this can lead to a run-away situation if the rule continues
	to return success state. If the rule is not looping with a success state
	the processing ends for this stepping of the behavior tree. It is
	recommended to not use looping on the root rule uness you have a
	specific need to do so.
 
	Looping rules can be used anywhere in the behavior tree for both
	sequence and choice rules. Looping can be useful in some situations.
 
	This choice is structed in a way all regular actions come first. One of
	them is going to succeed so the interruption rule is never used. This
	rule is only jumped to directly hence the name. It would be also possible
	to embed the interruption behavior into the regular processing of the
	behavior tree. In this case interruption actions would only be possible
	after another action finished running.
 
	Rules are not required to have identifiers under certain circumstances.
	Identifiers are used by these actions:
	- Mandatory: Switch current rule (jumping) from script code
	- Mandatory: Saving behavior tree context state to save states
	- Optional: Debug logging to identify what rule is processed
	For mandatory usage an exception will be thrown if rule identifiers are
	null. If a rule only returns success or failure state and never returns
	running state the identifier can be skipped. This works since only
	running rules can be the current rule and thus only the identifier or
	such rules are saved to file writers. If you never intend to save state
	nor jump to rules you can skip them entirly.
	-->
	<choice id='root'>
		<!--
		Choice of behaviors reacting to player getting too close.
 
		This rule is jumped to directly if the player gets close. This makes
		this rule an "interruption" rule. Such rules can be jumped to directly
		but also work if run inside regular AI looping. Jumping to simply
		makes the actor react immediatly. Without jumping the actor would
		react after finishing his current sequence of actions.
 
		To make writing identifiers simpler a trick can be used. If the
		identifier begins with a period the parent rule identifier is used
		as prefix. For example the ID ".child" inside a parent with ID "parent"
		becomes "parent.child".
		-->
 
		<!--
		Wander to a random position. This rule keeps running until the actor
		arrives at the target. The action succeeds once the actor arrived at
		the desired position. This action fails as long as player is too close.
 
		This action has a 25% chance.
 
		The attribute "name" defines the action to run and has to match a
		BTAction present in the game scripts.
		-->
		<action id='wander' name='wander'>
			<!--
			Parameters have string key and value. The action-tag and custom BTAction
			subclasses can use these parameters to modify the way the selected action
			runs. Certain conditions and custom BTCondition subclasses can also use
			the same parameters to modify the run checks.
 
			Since parameters are shared across all these elements care has to be taken
			how the parameters are named. If for example two conditions use the same
			parameter name they will receive the same value. If you need unique values
			for specific types of conditions you have to choose individual parameter
			names in your game scripts when adding the conditions to the context to
			allow you to define them separately in your behavior trees.
 
			The condition and parameter tags can appear in any order.
			-->
			<parameter name='chance'>0.25</parameter>
 
			<!--
			All actions use this condition to be interrupted. This could be also
			achieved by jumping to a specific rule manually. In this example the
			actions contain the interrupt condition.
 
			Each rule can have any number of conditions. The conditionMode states
			how the rules are checked. Supported are these modes:
			- allTrue: no condition returns false
			- anyTrue: at least one condition returns true
			- anyFalse: at least one condition returns false
			- allFalse: no condition returns true
 
			If complex conditions are required it is best to model them in the
			game scripts as a separate named condition. This increases the
			flexibility and avoids complicated XML for non-trivial situations
			-->
			<conditionMode>allFalse</conditionMode>
			<condition>playerNearby</condition>
 
			<!--
			The above condition is an example. To keep conditions more compact
			you can create a negated version of the condition. This has been
			done in the two actions below.
			-->
		</action>
 
		<!--
		Randomly rotate. This action has a 35% chance.
		-->
		<action id='turning' name='turning'>
			<parameter name='chance'>0.35</parameter>
			<condition>playerNotNearby</condition>
		</action>
 
		<!--
		Wait a random amount of time. This action has a 100% chance.
		-->
		<action id='wait' name='wait'>
			<parameter name='chance'>1</parameter>
			<condition>playerNotNearby</condition>
		</action>
 
		<!--
		If the player is close enough and moving fast the actor tries to
		flee by running and does a little jump for show. If any condition
		is false this action is not triggered.
 
		Condition checks are best done inside the action itself instead of
		using a construct like this:
		<sequence>
			<condition>isConditionTrue</condition>
			<action>doAction</action>
		</sequence>
 
		Using this construct is not wrong but prevents actions from being
		interrupted if a condition changes. The condition in the example
		above would be evaluated when the sequence is first entered and
		whenever an inner action fails and the next one is tried.
 
		To make writing the identifiers simpler a trick can be used. If the
		identifier begins with a period the parent rule identifier is used
		as prefix. In this example the ID ".flee" becomes "interrupt.flee". 
		-->
		<action id='flee' name='flee'>
			<condition>playerNearby</condition>
		</action>
 
		<!--
		If the player is close enough and not moving fast the actor tries
		to increase his distance to the player by walking. If any condition
		is false this action is not triggered.
		-->
		<action id='backOff' name='backOff'>
			<condition>playerNearby</condition>
		</action>
 
		<!--
		If we end up here no event condition is true. We want to loop again
		so we need to use the success rule. Using failure instead (same as
		doing nothing here) would fail the behavior tree and throw an exception.
 
		This is a good example where rule identifier is not required since the
		rule never returns running and thus never will be the current rule
		after the behavior tree finished stepping. Another such rule is
		<failure/> which always fails.
		-->
		<success/>
	</choice>
</behaviorTree>
You could leave a comment if you were logged in.
dragengine/modules/dragonscript/behaviortrees.txt · Last modified: 2025/03/13 18:31 by dragonlord