quantum | v2 switch to V1  

Blackboard

Contents

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.

Back To Top
 

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.

Back To Top
 

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:

Blackboard Visual Editor Empty

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.
Blackboard Visual Editor Creating Entry

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

Blackboard Visual Editor Many Entries

The types currently supported by the Blackboard are:

  1. Boolean;

  2. Byte;

  3. Integer;

  4. FP;

  5. Vector2;

  6. Vector3;

  7. 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 Assets

Back To Top
 

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.

Blackboard Assets

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:

Blackboard Assets

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.

Blackboard Assets

Back To Top
 

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.

Back To Top
 

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

To Document Top