# Quick Start Guide ## What is Behavior Bricks? Behavior Bricks is a plug-in for Unity3D that let you design the Artificial Intelligence (AI) for Non-player Characters (NPCs) in a graphical way. Using _behavior trees_ as the graphical modelling language, Behavior Bricks provides rich and ready-to-use actions and conditions waiting for you to use them. But, if they are not enough for developing your next awesome game, you can always extend the built-in library using a powerful API. Behavior Bricks helps you in that task too, organizing your home-made behaviors in such a way that reusing them (in other games, or even in more complex behaviors) becomes a child's play. This quick start guide shows you the basics of Behavior Bricks through the creation of your firsts behaviors; this should be enough for providing the first insights into the behavior editor. The guide assumes you have some previous experience using Unity3D, so it will not detail every single step done with it. You are also supposed to have been loaded Behavior Bricks into a new Unity project. Refer to the download instructions in other case. The final scene of the guide is available in the Behavior Bricks package, under `Samples\QuickStartGuide\Done` folder. The behaviors are available in the same folder in the Collection (more about it later). ## Creating the project and the scene Start by creating a new 3D project and importing BB package ... In this tutorial we create a small scene with two interactive game objects. The first one represents the player, and is moved around using mouse clicks. The second one is an "enemy" that wanders around, and pursues the player when sees him. For simplicity, all the models of the scene are basic primitives, so no assets are needed. If you feel bored of setting up the initial scene, you can use the premade `InitialScene` in the `Samples\QuickStartGuide` folder of the Behavior Bricks package (remember to make a copy if you want to keep the original empty version). In other case, you should take the next steps: - Create a plane (GameObject - 3D - Plane) and rename it to `Floor`. Set the position to (0, 0, 0), and the scale to (5, 1, 5) so it covers a bigger area. Check the `Static` checkbox near the Game Object name in the Inspector. - Move the main camera to (0, 20, -30), and set the rotation to (45, 0, 0) in order to fit the plane into the view. - Create a sphere for the player. Rename it to `Player`, and place it in (0, 0.5, 0) so it will be over the floor. - Create a cube for the enemy. Rename it to `Enemy`, and place it in (20, 0.5, 20). It will be quite far away from the player, near the plane limits. - Create three new materials, `Green`, `Blue` and `Red` with those flat colors and use them for the floor, player and enemy respectively. - Create the _navitation mesh_ that will be used by both the enemy and the player for pathfinding. Select the floor, go to Window - Navigation and press the _Bake_ button. If you have not yet saved your scene, Unity will ask you to do so now. ![]( :images:design:BakeNavigationMesh.png ) The scene should be set up now. ![]( :images:design:InitialScene.png ) ## Wander: the first enemy behavior It's time to create our first simple behavior for the `Enemy`. Go to the Behavior Bricks menu (Window - Behavior Bricks), and open the editor. That will open the _Behavior bricks editor_. Keep in mind that the window behaves like any other window in Unity3D: it can be dragged to any location so you are able to customize your workspace as desired. The first step is to create a new behavior tree by writing its name in the text field at the upper part of the `Collection` tab and cliking the `Create new behavior` button. Although it is not important for this tutorial, you can create a hierarchy using `/` in the name (for example `Basic/Wander`). Also you can notice that the name used in the Inspector and the asset name are independent, although in this example we have chosen to make it the same, as shown in the figure. ![]( :images:design:CreateNewBehavior.png ) Once the new behavior asset has been saved it will appear in the `Behaviors` list and will be opened as a new tab in the behavior graphical editor, showing an initially empty canvas. In order to add a new node to the behavior you just need to right-click on any empty point of the canvas and choose one from the drop-down menu. In order to simplify the search, a text field is available for filtering the elements by name in the menu. Browse the hierarchy to have an idea about the built-in actions, conditions, behaviors and composite nodes. ![]( :images:design:BBEditor.png ) Our first step will be to make the enemy go to a fixed position, in (-20, 0.5, 20), moving parallel to the upper floor edge. - In the canvas for the `Wander` behavior add a new node for the action `MoveToPosition`. You can type `move` in the search box to quickly find the action in the drop-down menu. - Click on the new node to select it (a yellow border appears when selected) and click on the `Node` tab in the Behavior Bricks inspector. This tab shows the propoerties of the selected node in the canvas. In this case you will find the _input parameters_, that constitute the information the action needs to know how to proceed. `MoveToPosition` needs the target position, a `Vector3`. Set the values to (-20, 0.5, 20). ![]( :images:design:WanderFirstSteps.png ) - All changes are automatically saved in your project so, once done, you can close the Behavior Bricks editor. At runtime, behaviors are executed by the _behavior executor_, a component that must be added to any game object that would be controlled by Behavior Bricks. Select the `Enemy` and add the component Behavior Bricks - Behavior Executor. ![]( :images:design:AddingTheExecutorComponent.png ) The new component shown in the Inspector provides a place to drop the behavior to execute. From the asset folders, look for the 'Wander' behavior, and drop it in the Behavior variable. Launch your project and you will see the `Enemy` moving to his left. Be aware of the Unity warning "_The Enemy game object does not have a Nav Mesh Agent component to navigate. One with default values has been added_". This is due to a missing component in the `Enemy`. Specifically, `MoveToPosition` action uses the scene nav mesh, which requires a nav mesh agent component. Unity automatically adds it on runtime when missing, and warns about that. You can avoid the warning adding that component beforehand yourself. ## Generalizing behaviors: the blackboard Our behavior moves the `Enemy` to (-20, 0.5, 20), a position hard-wired directly in the behavior. This is usually a bad idea. Keep in mind that we could have _more than one game object_ sharing the same behavior and we usually will want to finetune some parameters of the behavior in order to provide diversity. We can, then, do this better generalizing the behavior using the _blackboard_. The behavior blackboard acts as the _behavior memory_, structured by means of attribute-value pairs. Actions like `MoveToPosition` can read their parameters from there instead of using hard-wired constant values and, even better, the blackboard can be configured externally from the game object Inspector. - Open the `Wander` behavior in the editor, and select the `MoveToPosition` action. - In the BB Inspector, go to the _input parameters_ in the `Node` tab and note the combobox where `CONSTANT` is selected by default. Change it to `BLACKBOARD`. The old value (-20, 0.5, 20) will be substituted by a text field to define a new blackboard parameter. - Name it `wanderTarget` and click the `Create` button. - Now in the `Blackboard` tab of the BB Inspector we can find the new _behavior input parameter_ with that name. You can change the value for the parameter there. ![]( :images:design:FirstBlackboardParameter.png ) As seen, the value for the new blackboard field can be globally changed in the behavior properties. But, more interesting, it can also be changed in the behavior executor component properties: - Close the editor. - Select the `Enemy` game object if needed. - Check the behavior executor component. Note the new _behavior param_, `wanderTarget`. - Change the value to (-20, 0.5, 20) in order to mimic the initial configuration. ![]( :images:design:blackboardParameterInTheComponent.png ) Although it is not needed for this tutorial, it is possible to assign the same `Wander` behavior to as many game object as desired, using different `wanderTarget` values for all of them, creating diversity. The value provided for the `wanderTarget` parameter _in the behavior_ becomes a _default value_ used for those game objects that have not had it changed in their executor component. This acts in a similar way to the values in the _prefabs_ and their instances. ## Composing behaviors: internal nodes A wander behavior that just goes to a fixed position is hardly motivating. We will improve it selecting a random position. - Open again the editor and edit the `Wander` behavior. - Add a new node to the canvas for the `GetRandomInArea` action. When executed, this action chooses a position from an area (specified by means of a Game Object) and returns it as an output parameter. - Check the _action parameters_ in the BB Inspector. Note the `area` _input_ parameter, and the `randomPosition` _output_ parameter. - Create a new blackboard parameter for the first one and call it `wanderArea`. - Select the previous `wanderTarget` as the blackboard parameter where the action will write the selected position. ![]( :images:design:GetRandomInAreaProperties.png ) The key point here is that the actions `GetRandomInArea` and `MoveToPosition` are now connected through the `wanderTarget` blackboard parameter. - Close the editor and select, if needed, the `Enemy` game object. - Note the behavior executor component. Now it has _two_ parameters, the old `wanderTarget` and the new one `wanderArea`. ![]( :images:design:WanderParametersInComponent.png ) - `wanderTarget` is actually an _internal_ value that should not be manipulated from the outside. It is something like _temporal information_ that the behavior needs, but that is unimportant when using the behavior in a game object. - Open again `Wander` behavior in the editor. - Click on the `Blackboard` tab of the BB Inspector and notice that _both_ parameters, `wanderTarget` and `wanderArea` are labeled as "`IN`". - Change the type of the `wanderTarget` parameter to "`LOCAL`". ![]( :images:design:ChangingBlackboardParamType.png ) - Note that now the `wanderTarget` parameter has disappeared from the behavior executor component in the `Enemy`. In this moment we have two actions in our behavior but what of them will be executed earlier? Obviously, we want the `GetRandomInArea` to be executed before `MoveToPosition`, but if you observe both actions, you will notice the `R` in the upper-right corner of one of the nodes. ![]( :images:design:TwoActionsWithNoParent.png ) The action marked with an _R_ (`MoveToPosition`) is the root of the behavior tree and will be executed in the first place. In fact, `GetRandomInArea` will _not be_ executed at all. In order to create a behavior with _two_ actions, we need to _compose them_. - Right click on the canvas an add a composite `Sequence Node`. The concrete position is unimportant: you can move it afterwards. Arrange the nodes in a way similar to the figure. A `Sequence` is a composite node that executes _its children_ in order. ![]( :images:design:AddingASequence.png ) - Click on the bottom _handle_ in the `Sequence` and then click on top handle of the `GetRandomInArea` node. This will create a _connection_ relating both _nodes_. A connection can be easily removed by right clicking on it and selecting `Remove connection` in the drop-down menu. - Create a new connection from the `Sequence` into `MoveToPosition`. Observe that the `R` marking the root moves to the `Sequence` node. Our behavior _is now a valid tree_. The executor will start with the sequence, that will, in turn, execute the `GetRandomInArea` action and then the `MoveToPosition` one, following a left-to-right order. The order is marked by numbers in the top right corner of the node, and can be altered just by dragging the nodes. For example, by dragging the `MoveToPosition` node to the left of the `GetRandomInArea` node we can alter the order of execution of the sequence children. ![]( :images:design:CreatingASequence.png ) - The sequence executes its children _once_. We want the enemy to continually wander around, so when it reaches the random position, another one should be selected and the enemy should go there. - Insert a `Repeat Decorator` node into the canvas. This internal node executes its child behavior again and again. - Create a connection from the `Repeat` node to the `Sequence`. Observe how the `R` mark readjusts itself. ![]( :images:design:WanderBehavior.png ) - Close the editor. Remember that behaviors are automatically saved. If needed, or if you haven't used the "InitialScene": - Select, the `Enemy` game object and observe the behavior executor parameters. Remember that the `wanderArea` is still unestablished so the `GetRandomInArea` does not know the area where the position should be chosen from. Specifically, `GetRandomInArea` requires a game object _with a box or sphere collider_. - Select the `Floor` game object, and add it a Box collider. Set (10, 0, 10) as its size. - Select the `Enemy` game object, and drag and drop the `Floor` into the `wanderArea` parameter. - Play the scene. Observe the wander behavior of the enemy. It will continually move around to random positions. The final version of this `Wander` behavior is available as `Done Wander` in the Behaviors Collection. ## Conditions and perception: nodes that fail Although Behavior Bricks is mainly designed for creating the NPC and tactic or strategic AI, it can also be used for creating any other game logic, as menu control, HUD movement or even dynamic music manipulation. In this section we will create a behavior _for the player_, that will let us introduce new actions and our first condition. We want the player to move around using the mouse. This requires three steps: - Detect the mouse click. This provides us with a coordinate in _screen space_ (2D). - Convert the click position into a 3D coordinate using a _raycast_ to detect the object under the mouse. - Ask the player avatar to move to that position. _When_ the user clicks the screen, his avatar will move to that position, so we need to create a behavior that _feels_ the environment and acts according to it. This _perception_ is managed through _conditions_. Conditions are nodes that, when reached, end immediately and inform their parent nodes whether they were evaluated as `true` or `false`. In behavior jargon, when a node returns `false` it is said to _fail_, and to _succeed_ if returns `true`. The distinctive feature of the internal composite nodes (`Sequence`'s and `Repeat' `s are the only ones we have used so far) is how they react to the values returned by their children conditions (if they _fail_ or _succeed_). In this section we will use the built-in `CheckMouseButton` condition that test if the user has just pressed one of the mouse buttons and ends with success in that case. - Open the editor window and create a behavior with the name `ClickAndGo`. - Add a `CheckMouseButton` node into it (remember the use of the search box). Note that this node is under the `Condition` branch and it has a different color. - Check its parameters. Confirm that the `button` is set to `Left`, so the condition will check if the user has pressed the left mouse button. - Add a `FromMouseToWorld` action. This action convert the current mouse position from screen coordinates to world coordinates. It has four parameters: - `camera`: camera used for the translation. Add a new blackboard field and keep the default name, `camera`. - `mask`: layer mask used for filtering the raycasting. Add a new blackboard field and keep the default name. - `selectedGameObject`: an _output_ parameter where the action will write back the game object under the mouse, if any. We are not interested on it in this behavior, so we will keep it unassigned. - `selectedPosition`: _output_ parameter with the 3D position of the mouse relative to the chosen camera. Add a new blackboard field and keep the default name. - Add a `MoveToPosition`. Change its `target` parameter to the `selectedPosition` field in the blackboard. - In the `Blackboard` tab change the `selectedPosition` parameter type from `OUT` to `LOCAL` because it is not relevant for the game object. - Add a `Sequence` and make those three nodes its children. - Add a `Repeat` node so the sequence loops again and again and the user can move around to different positions. ![]( :images:design:ClickAndGo.png ) - Close the editor and add a Behavior executor component in the `Player` game object. Attach to it the `ClickAndGo` behavior. - Configure the `camera` parameter with the `Main Camera`, and set the `mask` to `Everything`, so the screen-to-world transformation is done using the camera view, and the raycasting considers all objects in the scene. - To avoid the warning on runtime, add the nav mesh agent component to the `Player`. - Play the scene and click around and note that now the player moves to the selected positions. It is worth mentioning that while doing the behavior, we have completely ignored the fact that the `CheckMouseButton` condition returns a value. When a child condition succeeds (returns `true`), `Sequence`'s will continue executing their next child, if any, with no delay. But if a condition fails (returns `false`), they will end immediately and fail themselves. As you might expect, `Sequence`'s succeed when they have executed all their children and none has failed (returned `false`). For our example, it is also important how `Repeat` nodes react to conditions. When playing the scene, is likely that the user does not press the left mouse button in the very first game loop. So the `CheckMouseButton` will end with failure. That will cause the `Sequence` to also fail, and so the `Repeat`. The `Player` behavior will then end immediately (with failure) and the behavior executor will not have anything to do afterwards. Fortunately, we can configure the `Repeat` node _policy_. - Open the `ClickAndGo` behavior in the editor. - Select the `Repeat` node. - Observe the Inspector and note the policy combo box. By default, it is set to "Continue when child fails". This will force the `Repeat` node to retry its child even when it has ended with failure. Just in case you are wondering, the `Sequence` node _has not_ a configurable policy similar to that one in `Repeat`. As said before, the way sequences react to children failures is in fact the decisive feature that make them sequences in the first place. If you need an internal node that _tries_ the next child when the previous one fails, then you would want to use a `Selector`. Selectors end as soon as one child ends with success, and execute the next child when the preceding one has failed. Currently, both the enemy and the player move at the same speed. - Select the `Player` game object. - In the nav mesh agent component, set the speed to 7.0 so it will move faster. This will allow to run away from the enemy in the next sections. You can find the final behavior in the Collection with the name `DoneClickAndGo`. ## Changing your mind with priority selectors: wander and pursuing Now that the player can move around, the enemy seems quite dump because he moves around completely ignoring the player. In this section we will create a new enemy behavior that will pursue the player when he is "seen", and will come back to a home (fixed) position in other case. Note that, in fact, this behavior _includes other two_. The preferred behavior is pursuing the player. But this is only possible if the player is near enough to be seen. In other case, the enemy will execute the fall-back behavior consisting on moving to the home position. As soon as the player falls in the enemy field of influence, that movement should be aborted and the preferred behavior started. This composition of behaviors with _different priorities_ is achieved through the `Priority` composite node. It is a _selector_ in the sense that as soon as one of its children ends with success, it also ends. But each child has a _condition_ that must be true in order to launch it. And, more important, when a child is being executed, _all_ the conditions of preceding sibling nodes are evaluated and, if any of them becomes true, the less priority behavior is immediately aborted and that one is started. - Create a new behavior and name it `EnemyBehavior`. - Add a `Priority Selector Node` into the canvas. - Add an action `MoveToGameObject`. It is similar to the known `MoveToPosition` but the parameter will be a game object instead of a concrete 3D position. - Add a new blackboard field for the `target` parameter and name it `player`. - Create a connection from the `Priority` to the `MoveToGameObject`. Note the yellow node that appears on top of the `MoveToGameObject` action. Every child of a priority must be a guarded node composed of a condition plus an action (or behavior). Therefore when a `Priority` node is connected to a `MoveToGameObject` node, a default `AlwaysTrue` condition is automatically added to guard the `MoveToGameObject` action node. ![]( :images:design:DefaultPriorityCondition.png ) - Select the `AlwaysTrue` node, right-click on it and select `Replace with ...` in the drop-down menu, and finally select `IsTargetClose` in the list of available conditions. ![]( :images:design:ChangingPriorityCondition.png ) - `IsTargetClose` has two parameters: - Set the `target` parameter to the `player` blackboard field. - Set 15 as the close distance. - Add a new `MoveToPosition` node and make it the second child of the priority, becoming the fall-back behavior. This time instead of first creating the action and then connecting it to the priority, click on the bottom connection area of the priority, then click on an empty point in the canvas, and finally select `MoveToPosition` in the drop-down menu. Set the `MoveToPosition` `target` parameter to the constant value (-20, 0.5, 0). ![]( :images:design:PursueOrGoHome.png ) - Close the editor and set the new behavior to the enemy, substituting the previous one, `Wander`. Note that the old one will not be removed from your behavior Collection. - Set the `player` parameter to the `Player` game object. - Play the scene. The enemy will move to his home position (in the center of the left floor edge). In the middle of his path, the player will enter in his influence radius and the more priority action `MoveToGameObject` will be triggered. - Run away from the enemy using the mouse. - Note that, once far enough, the enemy stops pursuing the player and go to his home position. Once there, the enemy will not pursue the player any longer. A `Priority selector` ends when their children end, so the behavior finishes when the enemy reaches its home position. Make the `Priority` child of a new `Repeat` node, and play the scene again. Now the enemy will pursue the player even when he is in his home position. ## Composing bricks: reusing behaviors Behavior bricks promotes behavior reusability not only because behaviors can be used simultaneously in many game objects, but because behaviors can be used as _black boxes_ in other ones. In that way, the _Collection_ becomes the cornerstone of the reusability in Behavior Bricks. - Open the `EnemyBehavior` in the editor. - Remove the `MoveToPosition` action by selecting it and pressing the `Delete` key (`Backspace` in Mac). - Add a new node selecting the `Wander` behavior in the drop-down menu. Note that this is the behavior we made in a previous section. If you double click the node you will open it in a new tab, and any change done to the `Wander` behavior will also affect its reference included in `EnemyBehavior` . Dropping it into the `EnemyBehavior` canvas _incorporates it_ as any other action. - Select the `Wander` node and check its parameters in the `Node` tab of the BB Inspector. Note the `wanderArea` in the behavior parameters. This is the only `IN` blackboard parameter included in the `Wander` behavior. When we used the behavior in the executor component, the parameter had to be set in the game object Inspector. When used in a bigger behavior, such as `EnemyBehavior`, it must be configured directly in the editor of the using behavior. - In this case, we want to "publish" this parameter towards the `EnemyBehavior` users. Assign it a new blackboard parameter and keep the default name, `wanderArea`. - Check the `Blackboard` tab to see the behavior properties in the Inspector, where two `IN` parameters must be shown: `player` and `wanderArea`. - Make the `Wander` node the fall-back (`AlwaysTrue`) child of the `Priority`. ![]( :images:design:ReusingABehavior.png ) - Remember to assign the Floor GameObject to the wanderArea parameter in the Unity Inspector. - Play the scene. Now the `Enemy` wander around to random places. When he perceives the player, he abandons his wander behavior and starts pursuing. If the player runs away from him, then he starts wandering again. As always, you can find the final behavior in the Collection under the name `DoneEnemyBehavior`. ## Initializing the input parameters of a behavior tree from code In certain situations it may be interesting to create a `prefab` of an entity that has a `Behavior Executor` component in it. In those situations the input parameters of the behavior tree executed by the behavior executor can not be initialized with objects from a scene, since Unity does not allow a prefab to be configured with objects from a scene that may or may not exist when the prefab is instantiated. In this case, we can use a `spawner` object that can be configured through the Unity inspector and can instatiate the prefab and configure its behavior executor via code. As we will see later this open a number of possiblities for creating and configuring game objects that execute different instances of behavior trees. First, create a prefab from our current `Enemy` object in the scene and delete it from the scene. The prefab has lost the values that were asigned for the `wanderArea` and `player` parameters in the `Behavior executor` of the `Enemy` game object. Then, we are going to create a `Spawner` script to instantiate and configure the enemy prefab: - Create a new C# script and name it `Spawner.cs`. - Open it into your preferred editor and substitute the default code with: ```csharp using UnityEngine; public class Spawner : MonoBehaviour { public GameObject prefab; public Vector3 position; public GameObject wanderArea; public GameObject player; void Start () { GameObject instance = Instantiate(prefab,position,Quaternion.identity) as GameObject; BehaviorExecutor behaviorExecutor = instance.GetComponent(); if (behaviorExecutor != null) { behaviorExecutor.SetBehaviorParam("wanderArea", wanderArea); behaviorExecutor.SetBehaviorParam("player", player); } } } ``` Once you have finished, create an empty `GameObject` named `Spawn` in the scene, add the `Spawner` component, and set the component variables: - In the `Prefab` field asign the `Enemy` prefab created in this section - In the `Position` field set the following values: `X=20, Y= 0.5, Z = 20` - In the `Wander Area` field drag the `Floor` object from the scene - In the `Player` field drag the `Player` object from the scene ![]( :images:design:SpawnParameters.png ) ![]( :images:design:SpawnScene.png ) Now play the scene and everything should work as before. ## In Behavior Bricks efficiency matters Once we can create and configure through code instances of prefabs running behavior executor components, we can multiply the number of enemies. In the next example we will create a spawner component that creates a given number of enemies at random positions and randomly make them follow the player or one of the previously created entities. - First duplicate the scene we have been working with - Remove the `Spawner` component from the `Spawn` object - Create a new C# script and name it `MassSpawner.cs`. - Open it into your preferred editor and substitute the default code with: ```csharp using UnityEngine; using System.Collections; using System.Collections.Generic; public class MassSpawner : MonoBehaviour { public GameObject prefab; public GameObject wanderArea; public GameObject player; public int Spawns = 750; int spawnCount = 0; List entities; void Start() { entities = new List(); entities.Add(player); InvokeRepeating("Spawn", 0f, 1.0f / 1000.0f); } void Spawn() { if (spawnCount <= Spawns) { GameObject instance = Instantiate(prefab, GetRandomPosition(), Quaternion.identity) as GameObject; BehaviorExecutor component = instance.GetComponent(); component.SetBehaviorParam("wanderArea", wanderArea); component.SetBehaviorParam("player", entities[Random.Range(0, entities.Count)]); ++spawnCount; entities.Add(instance); } else { CancelInvoke(); } } private Vector3 GetRandomPosition() { Vector3 randomPosition = Vector3.zero; BoxCollider boxCollider = wanderArea.GetComponent(); if (boxCollider != null) { randomPosition = new Vector3( Random.Range( wanderArea.transform.position.x - wanderArea.transform.localScale.x * boxCollider.size.x * 0.5f, wanderArea.transform.position.x + wanderArea.transform.localScale.x * boxCollider.size.x * 0.5f), wanderArea.transform.position.y, Random.Range( wanderArea.transform.position.z - wanderArea.transform.localScale.z * boxCollider.size.z * 0.5f, wanderArea.transform.position.z + wanderArea.transform.localScale.z * boxCollider.size.z * 0.5f)); } return randomPosition; } } ```csharp - Add the `MassSpawner` component to the `Spawn` object - In the `Prefab` field asign the `Enemy` prefab created in the previous section - In the `Wander Area` field drag the `Floor` object from the scene - in the `Spawns` field you can specify the numher of enemies to spawn ![]( :images:design:MassSpawnerParameters.png ) Once the enemies have been spawn you can check the scene stats, by pressing the `Stats` button in the `Game` pannel, and see how many frames per second (FPS) are you getting, 50 in the example shown in the figure. ![]( :images:design:PerformanceTest1.png ) One way to increase the performance without decreasing the number of spawns or making modifications to the behavior tree is to modify the field `Max Task Per Tick` of the `Behavior Executor` component of the `Enemy prefab`, by default its value is 500. Set it to `1`, play the scene again and see how it affects performance. In this case our frame rate increases up to 65 FPS without apparently affecting the observed behavior of the enemies. ![]( :images:design:PerformanceTest2.png ) ## What's next? Congratulations! You've just finished the first Behavior Bricks tutorial. You have learned the basics of the editor, and the main concepts: actions, conditions, blackboard, internal nodes, and reusability. If you want to test your newly acquired knowledge, you can, for example, improve the player behavior. Currently, once a position has been selected, it cannot be changed until the player avatar has reached it. It would be great if the player could select a different position using the mouse to overwrite the previous one. Using a priority selector it is easier that it sounds! And it you need some inspiration, you can always have a look at the behavior in the Collection. Finally, remember if you have had any problem following this tutorial, you have available the final scene in the `Samples\QuickStartGuide\Done` folder of the Behavior Bricks package.