Blackboard
Contents
- Introduction
- A Very Simple Example
- The Blackboard On The Visual Editor
- Blackboard Nodes
- When To Use The Blackboard And Its Nodes
- Blackboard Quantum Code
Introduction
The Blackboard is another very useful tool contained in the Bot SDK.
It is a set of Keys/Values that you can use to have your own customized data. It works pretty much like having custom data stored on components, but the main difference is that it is very dynamic as it can be created on the Visual Editor on Unity, instead of needing to create and recompile things on the DSL.
It is like a read/write memory for Actions and Decisions that you can have per agent.
The Blackboard is also designer friendly as it is totally defined using data assets and can be completely created using only the Visual Editor.
So you can have your blackboards stored and organized on your Unity project.
PS.: it is important to notice that the Blackboard data assets are just the memory layout definition.
If you have many Bots/Entities which should have the same memory layout, then all of those can point to the same Blackboard asset.
Each of those bots will then have its own memory created at runtime based on the layout defined.
A Very Simple Example
So, lets say that you have a character which collects some items on the map.
On your Actions and Decisions, you might want to read the amount of items that the character already collected in order to make a specific decision.
Also, if the character collects one more item, the items count should increase.
For this, you can have an entry on your blackboard, named ItemsAmount
of type Integer and manage it on your actions and decisions code.
As the every entity has its own blackboard memory created at runtime, it means that one entity can even read other entities blackboard memories. So the blackboard memory is not only one, shared between all the agents -- it is one per agent.
The Blackboard On The Visual Editor
The Visual Editor already comes with a sub-menu for the Blackboard.
It is named Blackboard Variables and it is accessible on the left side panel:

Press the + button in order to create new blackboard variables.
When creating/editing a new entry, you need to define:
- The variable's
Name
, which is internally used as a Key on the blackboard asset to retrieve some variable's value; - The variable's
Type
, which you can select from the dropdown menu; - The
HasDefault
checkbox, used to inform if this variable will or not be initialized to a default value upon setup; - The
Default
value to be used.

You can have many entries, with many types and it is not mandatory to always have default values defined.:

The types currently supported by the Blackboard are:
Boolean;
Byte;
Integer;
FP;
Vector2;
Vector3;
Entity Ref.
Now, whenever you compile your project, two extra data assets will automatically be created on the folder Assets/Resources/DB/CircuitExport/Blackboard_Assets
:
- A Blackboard asset which entries are the ones defined by the compiled HFSM;
- and a Blackboard Initializer asset which entries and default values are also the ones defined by the compiled HFSM.
One asset is related to the other. The first one defines just the layout, and the second one defines the values to be inserted when the blackboard is initialized.

Blackboard Nodes
With the variables in hand, you can drag and drop them to the graph in order to create Blackboard Nodes. These nodes always have two outbound slots: the Key
and the Value
.

The Key
slot is used to be linked to fields of type AIBlackboardValueKey
, which can be used to replace hardcoded strings when informing the key of the variable to get/set. And, of course, by removing the hardcoded keys, the code gets more flexible and reliable.
Let's analyze, in terms of quantum code, how the Get/Set methods should be used, depending if you are using a hardcoded key, or the key from a Blackboard node:
// -- Using hardcoded keys: --
var bbComponent = f.Unsafe.GetPointer<AIBlackboardComponent>(entityRef);
// To read
var value = bbComponent->GetInteger(frame, "someKey");
// To write
bbComponent->Set(frame, "someKey", value);
// -- Using keys from Blackboard nodes: --
public AIBlackboardValueKey PickupsKey;
// To read
var value = bbComponent->GetInteger(frame, PickupsKey.Key);
// To write
bbComponent->Set(frame, PickupsKey.Key, value);
With that new field declared, you can go to the Visual Editor and link it to any Blackboard Node's Key
slot to it. For example:
Besides of using the Key
slot like this, it is also possible to link the Value
slot to define fields of that same type (an integer blackboard variable linked to an integer field on some Action/Decision, for example). The Default
value defined on the left panel is the value which will be baked into the asset.
When To Use The Blackboard And Its Nodes
Use it whenever you want to store some data per-entity which can change during runtime. If you need to define values which will never change, consider using the Constants panel instead.
Blackboard Quantum Code
Initializing the Blackboard component
The important part for initializing the blackboard component is to have a reference to the AIBlackboardInitializer
asset which was created when you compiled your AI document on the Visual Editor.
Then, on your project's code, use this to initialize the component:
// -- Blackboard setup
// First, create the blackboard component (or have it created on the Entity Prototype)
var blackboardComponent = new AIBlackboardComponent();
// Find the Blackboard Initializer asset
var bbInitializerAsset = f.FindAsset<AIBlackboardInitializer>(runtimeConfig.BlackboardInitializer.Id);
// Call the static initialization method passing the blackboard component and the asset
AIBlackboardInitializer.InitializeBlackboard(f, &blackboardComponent, bbInitializerAsset);
// Set the blackboard into to the entity
f.Set(littleGuyEntity, blackboardComponent);
That's it. Once you've done all referencing and initialization, you are ready to read/write from the Blackboard using its API
// There is one method for each specific blackboard type (int, byte, FP, boolean, FP vectors and entityRef)
blackboardComponent->GetInteger(frame, key);
// For the setter method, there are different overrides depending on the type of data passed as the value
blackboardComponent->Set(frame, key, value);
Disposing the Blackboard component
When destroying an entity which uses the Blackboard component, it is important to free the component as to avoid memory leaks.
To dispose the blackboard memory, use blackboardComponent->Free(frame);
PS.: Bot SDK from version 1.0 RC2 and on already comes with some sample Actions/Decisions which reads/writes to the Blackboard.
On your quantum_code
solution, you can go to the folder BotSDK/Samples
and check the files IncreaseBlackboardInt.cs
, SetBlackboardInt.cs
and HFSM.CheckBlackboardInt.cs