-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc: migrate wiki to docsify page (#106)
Co-authored-by: Josephine Rueckert <[email protected]>
- Loading branch information
1 parent
c491071
commit 72e10a3
Showing
25 changed files
with
13,688 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,43 @@ | ||
# Behaviors | ||
Store for an assortment of behaviors that can be applied to creatures | ||
<div align="center"> | ||
<img src="./docs/_media/banner.png"> | ||
</div> | ||
|
||
_This is a module for [Terasology]. | ||
It provides a set of behavior traits that can be applied to creatures and NPCs._ | ||
|
||
<h2 align="center"><a href="https://terasology.github.io/Behaviors">👉 Documentation 👈</a></h2> | ||
|
||
## Contributing | ||
|
||
We welcome contributions to our modules, be it bug fixes or feature contributions. | ||
Check out the [Contributor Guide][contributor-guide] on the main project wiki to learn more. | ||
|
||
To check out this module (and all its dependencies) to your Terasology workspace run (in the workspace root): | ||
|
||
``` | ||
groovyw module recurse Behaviors | ||
``` | ||
|
||
To build a module JAR for just this module run (in the workspace root): | ||
|
||
``` | ||
gradlew :module:Behaviors:jar | ||
``` | ||
|
||
To run all tests and static code checks for this module run (in the workspace root): | ||
|
||
``` | ||
gradlew :module:Behaviors:check | ||
``` | ||
|
||
### Documentation via gh-pages | ||
|
||
The documentation of this module is build with [docsify]. | ||
It is served via [gh-pages]. | ||
To preview the site you can either use the `docsify` [CLI tool](https://github.com/docsifyjs/docsify-cli) or just run a static server on the `docs` folder. | ||
|
||
<!-- References --> | ||
[Terasology]: https://github.com/MovingBlocks/Terasology | ||
[gh-pages]: https://pages.github.com/ | ||
[docsify]: https://docsify.js.org/#/ | ||
[contributor-guide]: https://github.com/MovingBlocks/Terasology/wiki/Contributor-Quick-Start |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Actions and Decorators | ||
|
||
Actions and Decorators are what enables any entity to actually exhibit behavior - they are the 'final' nodes which make an entity do things, and as such will be, alongside with the actual behavior trees, the parts of the Behavior API most useful to someone wishing to give its entity behavior. | ||
|
||
## Class Structure | ||
|
||
Action and Decorator nodes are implemented by the `ActionNode` and `DecoratorNode` classes, respectively. | ||
Both implement the common `BehaviorNode` interface. | ||
|
||
An `ActionNode` is a leaf node and thus has no children | ||
|
||
A `DecoratorNode` has strictly one child. | ||
|
||
What is important to note is, `ActionNode` and `DecoratorNode` both use an associated `Action` to do their actual work. | ||
For every class with a `@BehaviorAction` annotation, a corresponding ActionNode or DecoratorNode is created, using the specified `Action` class as the action which provides the functionality (and using the `name` specified in the annotation to identify the node in the prefab files). | ||
|
||
This means that in order to create a new Action or Decorator, typically _you do not want to create a new Node, but create an `Action` instead._ | ||
|
||
> [!NOTE|label:Managing State on Actions and Decorators] | ||
> | ||
> In order to save substantially on memory and some performance, every ActionNode and DecoratorNode is created only once for a given behavior tree - these nodes are shared by all Actors running the same tree. | ||
> This means that **storing stateful information in the Action itself is a terrible idea!** | ||
> | ||
> In order to store and read state information, access the `Actor`'s `dataMap` instead, using the Action's `getId()` as an index. | ||
## `Action` and the `@BehaviorAction` annotation | ||
|
||
In order to create a new Action or Decorator for use in your behavior trees, you want to create a new class which implements the `Action` interface - extending `BaseAction` is the best way, as you can only focus on the functional parts of the action. | ||
|
||
In order for your `Action` to be discovered and loaded by the Behavior system, you need to annotate the class with the `@BehaviorAction` annotation. The format is: | ||
|
||
```java | ||
@BehaviorAction(name = "<name-of-your-action>") | ||
``` | ||
|
||
and if the `Action` is supposed to be used in a Decorator, you add the `isDecorator` parameter: | ||
|
||
```java | ||
@BehaviorAction(name = "<name-of-your-decorator", isDecorator = true) | ||
``` | ||
|
||
### Actions | ||
|
||
Actions are leaves - nodes with no children. These typically have an effect on the world or the state of the entity - such as the `move-to`, `set-target-work` or `play-sound` actions. | ||
|
||
An Action typically only needs to care about a few things: | ||
|
||
- `construct(Actor)` | ||
|
||
called when the node is first reached. Useful for setting initial state - don't forget to **[save all state at the actor!](#notyet)** | ||
|
||
- `modify(Actor, BehaviorState)` | ||
|
||
called each time the node ticks. If the action is somewhat continuous, most of the work will be here. The second argument is irrelevant to an Action. | ||
|
||
- `destruct(Actor)` | ||
|
||
called on the last tick of the node - when state changes from `RUNNING` to something final. | ||
|
||
- `setup()` | ||
|
||
a less used method - called right after all the fields are injected when the Action is being created. Can be useful if you need to load something once, but remember - all stateful data needs to be stored at the actor! | ||
|
||
### Decorators | ||
|
||
Actions designed for use Decorators implement the same methods as Actions designed as Actions, both related to the `DecoratorNode`'s child': | ||
|
||
- `modify(Actor, BehaviorState)` | ||
|
||
you now care about the second argument, which represents the `BehaviorState` returned by the child node. A Decorator often wants to react to it and/or modify it before returning its own state. | ||
|
||
- `prune(Actor)` | ||
|
||
called before update, return value decides whether to run child or not. Useful for condition-type nodes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# Big Picture | ||
|
||
Here, you can find an overview of some of the inner workings of the Behavior system. | ||
|
||
In Terasology, the Behavior system is composed of: | ||
|
||
- A Component `Behavior` used for associating entities with behaviors; | ||
- Two components `GroupTag` and `GroupMind` associated with groups; | ||
- An implementation of behavior trees and their related mechanisms (used to describe the behavior of an entity or a group of entities); | ||
- A decorated entity called `Actor`, used to facilitate the process of adding behaviors to a given entity; | ||
- An asset mechanism for loading `.behavior` and `.group` from the assets structure (on disk); and | ||
- An in-game editor for behavior trees (_currently unstable_). | ||
|
||
More details on each of the parts can be found below. | ||
|
||
## Components | ||
|
||
The `Behavior` component is used to associate an existing behavior with an entity or creature. | ||
Behaviors are structured as [behavior trees](Behavior-Trees) and are loaded as assets from [behavior files](Building-a-Behavior-Tree) (`.behavior`). | ||
This component holds two different objects: | ||
|
||
- A `BehaviorTree`, deserialized from a behavior file; and | ||
- An `Interpreter`, responsible for evaluating the behavior tree. | ||
|
||
The `GroupTag` component is used to assign an entity or creature to a group. | ||
Also, the `GroupMind` component is used in conjunction with `GroupTag` in specific group-related scenarios, where all entities within a group must possess not only the same behavior tree but also the same behavior states (acting in unison). | ||
For more details on how the group mechanism works please see [Groups](Groups). | ||
|
||
## Behavior Trees | ||
|
||
Behavior trees are the structures used to describe the behavior of an entity within the game. | ||
A behavior is a pre-defined set of actions performed by an entity, triggered by specific conditions or events. | ||
Behaviors can be related to movement (animals wandering in an open field) or more complex actions (searching for water sources to fulfill a specific need). | ||
A graphical illustration of a typical behavior tree is shown below: | ||
|
||
<fig src="images/big-picture/bt.png" alt="Example of a Behavior Tree">An example of a behavior tree.</fig> | ||
|
||
Behavior trees are composed of different _nodes_, which determine if the behavior will be performed sequentially, or if it will be subject to any conditions. | ||
The illustration above has _sequential_ nodes (right arrows), determining that everything below them will happen in a sequence (from left to right), and _condition_ nodes (question marks), determining that everything below them will happen (in sequence) only if a determined condition is satisfied. | ||
|
||
In Terasology, nodes are objects implementing the `TreeNode` interface. | ||
There are composite nodes, action nodes, and decorators, but in an effort not to duplicate information too much, see [Tree Nodes](Tree-Nodes) to learn about the `TreeNode` interface in detail. | ||
|
||
Every `Actor` instance (see description below) has an associated `Interpreter`. | ||
That interpreter uses a `BehaviorTreeRunner` (currently `DefaultBehaviorTreeRunner` as we aren't using the bytecode/ASM parts of the system) to work on the given tree - there is a `BehaviorTreeRunner` for every given Actor. | ||
What's important is the `BehaviorTree` is a data class; it provides the underlying tree data, but it's shared between Actors, using the Interpreter/BehaviorTreeRunner combo. | ||
|
||
Both `BehaviorTree` and `Interpreter` can also be instantiated and assigned to an entity during gameplay (for example, when entities join a group and must adopt a different behavior). | ||
In this case, the `BehaviorTree` instance is replaced by a new one, while the `Interpreter` can be created as a new instance or it can be replaced by another existing instance (this is particularly important in cases where an entity must not only assume the new behavior but also have its state placed in a specific point within the behavior tree). | ||
|
||
## Actor | ||
|
||
The Actor is a decorated Entity, a class that facilitates adds Behavior related functionality to a given Entity. | ||
It represents an entity with a behavior. | ||
|
||
Important parts of the Actor class: | ||
|
||
- `Actor(EntityRef)` constructor - an Actor can only be constructed over a given Entity. | ||
- `getEntity()` - returns the underlying entity. | ||
- `getComponent()`, `getComponentField()`, `hasComponent()` - QoL methods providing easier access to some parts of the underlying entity. | ||
- `save(Component component)` - assigns a component to the current Actor. This method is used when new components are assigned to the Actor, or in some cases when existing components are modified. | ||
|
||
Other important parts of the Actor class are: | ||
|
||
- `Map<Integer, Object> dataMap` | ||
|
||
_Used by every Behavior Node to manipulate its stateful information, so the Nodes themselves can be stateless/reusable. | ||
The `id` arguments used in its related `getValue()` and `setValue()` methods are the tree-unique IDs of the Nodes._ | ||
|
||
- `Map<String, Object> blackboard` | ||
|
||
_Used to facilitate inter-node communication. | ||
While in `dataMap` every node has its own little corner where it stores its info, `blackboard` is the shared space where nodes can co-ordinate any higher level stateful goals._ | ||
|
||
## Assets | ||
|
||
Behaviors are JSON-like files that describe a behavior tree, containing pre-defined elements (nodes) and actions associated with these nodes. | ||
These files (`.behavior`) are located in the `assets/behaviors` folder of each module. | ||
|
||
Each entity can have a behavior component included in its `.prefab` file as: | ||
|
||
```json | ||
"Behavior" : { | ||
"tree" : "<module>:<behavior>" | ||
} | ||
``` | ||
|
||
Where `<behavior>` refers to the name of the behavior, and `<module>` refers to the module in which the behavior is defined. You can use any pre-made behavior existing in another module. If you use the `stray` behavior from the Behaviors module, for example, your `.prefab` behavior entry will be: | ||
|
||
```json | ||
"Behavior" : { | ||
"tree" : "Behaviors:stray" | ||
} | ||
``` | ||
|
||
> [!NOTE] | ||
> Although you can omit the `<module>` prefix for behaviors defined in the same module, it is good practice to **always** use the fully qualified name. | ||
> | ||
> This makes it easier to extract and move behaviors to different modules, and it also avoids confusion between behaviors of similar or identical names from different modules. | ||
A curated list of pre-made behaviors can be found [here](Pre-made-Behaviors-and-Nodes). | ||
|
||
## GUI Editor | ||
|
||
Behavior trees can also be created or edited through the use of the Behavior GUI editor. | ||
The GUI editor is currently unstable, but its latest version can be accessed in-game through the <kbd>F5</kbd> key. | ||
|
||
> [!NOTE] | ||
> The UI editor is in a highly experimental state. | ||
> We recommend that you edit your `.behavior` files directly in a text editor of your choice. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# Creating a Behavior Tree | ||
|
||
Any given behavior tree is specified as a JSON-like asset in the module's `assets/behaviors` folder, with the `.behavior` extension: | ||
|
||
<fig src="images/Building-A-Behavior-Tree/behavior-tree-folder.png" alt="Behavior file assets in the module asset file tree">Behavior files are part of a module's assets.</fig> | ||
|
||
To create a new tree, just create a `<name>.behavior` file in your module's `assets/behaviors` folder and open it in your favorite text editor. | ||
|
||
## Tree file structure | ||
|
||
The actual tree definition files have a very simple structure: essentially, the `.behavior` file only represents the definition of the root (top-most) TreeNode, with all of its children/arguments, recursively. | ||
As an example, this is how the file `still.behavior` (originally from the `WildAnimalsMadness` module) is structured: | ||
|
||
```yaml | ||
{ | ||
sequence:[ | ||
{ | ||
animation : { | ||
play: "engine:Stand.animationPool", | ||
loop: "engine:Stand.animationPool" | ||
} | ||
}, | ||
{ | ||
sleep : { | ||
time : 3 | ||
} | ||
} | ||
] | ||
} | ||
``` | ||
|
||
### Nodes - the building blocks | ||
|
||
Every TreeNode is required to have a `name`. | ||
That name is pre-defined for the logic / flow control nodes and some special nodes - a reference of which is [here](https://github.com/Terasology/Behaviors/wiki/Control-Flow-Nodes) - and every Action and Decorator node has its name specified by the `name` field in its `BehaviorAction` annotation - more on that [here](Tree-Nodes). | ||
|
||
This `name` represents any and every Node in the JSON defining the tree. | ||
|
||
#### Simple Nodes, Actions | ||
|
||
A simple node with no arguments - which includes most Actions - is represented only by writing down its name: | ||
|
||
```yaml | ||
<node-name> | ||
``` | ||
|
||
#### Nodes with arguments | ||
|
||
A node which needs some arguments to be specified needs to be written down as an object: | ||
|
||
```yaml | ||
{ <node-name>: { argument-1: value-1, ? <..> | ||
argument-n | ||
: value-n } } | ||
``` | ||
|
||
In the case of **Decorators** (nodes with strictly 1 child), the child is provided as any other argument, in the form | ||
|
||
```yaml | ||
child: <node-definition> | ||
``` | ||
where `<node-definition>` can be any arbitrary node, including composite nodes or other Decorators. | ||
|
||
#### Composite Nodes | ||
|
||
A Composite (multiple-children) node is represented using an array: | ||
|
||
```yaml | ||
{ <composite-node-name>: [ | ||
<child-node-1>, | ||
<child-node-2>, | ||
<..> | ||
<child-node-3>, | ||
] } | ||
``` | ||
|
||
```yaml | ||
success | ||
``` | ||
|
||
> [!NOTE|label:A note on quotes and JSON] | ||
> While the JSON standard disallows keys not wrapped in double quotations, our GSON / deserialization implementation for the most part doesn't care about it - at least in terms of behavior tree files. | ||
> This means that this: | ||
> | ||
> ```yaml | ||
> { sequence: [{ timer: { time: 5 } }, { log: { message: Hello! } }] } | ||
> ``` | ||
> | ||
> is virtually identical to this: | ||
> | ||
> ```json | ||
> { | ||
> "sequence": [ | ||
> { | ||
> "timer": {"time": 5} | ||
> }, | ||
> { | ||
> "log": {"message": "Hello!"} | ||
> } | ||
> ] | ||
> } | ||
> ``` | ||
> | ||
> The variant without quotes is a bit more readable and less 'boilerplate-y', but both variants are possible. | ||
> | ||
> _However_, the canonical - quote-infested - version is the only one 100% officially supported, so if you run into issues with the tree file loading, it is a good idea to try if the issue persists with a canonical JSON version of the same tree. | ||
> | ||
> One very handy tool for converting the terse version into canonical JSON is [YAML Parser](http://yaml-online-parser.appspot.com/) - simply paste your tree definition into the left pane, and it spits out canonical JSON on the right. | ||
> It also catches many formatting / syntax errors (but not all, as YAML is a superset of JSON). | ||
|
||
## Examples | ||
|
||
You can find examples of behavior trees in action [here](Pre-made-Behaviors-and-Nodes). |
Oops, something went wrong.