
Behavior Tree Editor
This custom Behavior Tree Editor provides a streamlined way to create and manage AI logic using an Entity Component System (ENTT) with an intuitive node-based UI (based on ImNodes for ImGUI).
The system automatically handles serialization and editor integration, allowing developers to focus on AI logic. Additionally, it features a blackboard system, similar to Unreal Engine’s, enabling data storage and synchronization across multiple entities. While editing is PC-exclusive, the AI trees are fully functional on the PS5 as well.
I also wrote a blog post about this project which can be found here.
-
Role: Tools Programmer
-
Responsabilities:
-
C++ custom node creation
-
Editor UI
-
Blackboards
-
-
Team size: Solo
-
Tools/Language:
-
Custom engine
-
C++
-
Final Result
The Behavior Tree Editor streamlines AI behavior creation, providing a node-based interface (Fig. 1) and seamless C++ integration.
The result is a highly flexible system where AI behaviors can be visually structured while maintaining full control through C++. Once created, these behaviors (Fig. 2) can be used across multiple entities and even run on PC and PS5, ensuring a smooth development workflow from design to implementation.
Fig. 1

Fig. 2


Node based editor
-
Node-based workflow for AI behaviors using ImGUI with the ImNodes extension that is slightly modified to fit what I needed.
-
Each node represents an action, condition, or decorator, forming complex behaviors in a structured manner.
-
This visual system simplifies design and debugging of AI decision-making.

Fig. 2
Blackboards
-
Inspired by Unreal Engine's system, the blackboard stores keys (Fig. 2) that nodes can read or write to, representing the communication between them.
-
A unique addition are the "Custom Keys" (Fig. 1), which allow any node pin to act as a blackboard key. Instead of hardcoded values, pins can dynamically reference stored data, reducing the need for multiple C++ nodes.
-
To enhance usability, a validation system highlights valid keys in green and invalid ones in red (Fig. 1), ensuring clarity and efficiency.

Fig. 1
Serialization
-
Developed a template‑driven serialization framework using nlohmann::json (Fig. 1), where when a node is registered (Fig. 3) the following are created:
-
Builder - returns a factory lambda that instantiates std::shared_ptr<T> by name and ID, streamlining node creation in the editor (Fig. 2).
-
Serializer - will output the node in json format
-
Deserializer - will create the node based on the json data
-
-
The deserializer was the trickiest part because I had to make sure it was compatible even if the node changed in the meantime:
-
Reads basic data (ID, name)
-
Merges in default values for missing fields
-
Filters out obsolete custom keys
-
Reconstructs the node safely, ensuring backward‑compatible loading.
-
-
The user doesn't have to worry about serialization when creating new nodes and can focus on the functionality of the node.
Fig. 3
Fig. 1
Fig. 2

Personal Impact
-
This project was the one that led me down the path of tools development.
-
Seeing how much others enjoyed using it made me realize the impact a well-designed tool can have on a team’s workflow.
-
I discovered that working on tools allows me to explore multiple fields in depth, from UI and engine integration to AI systems and performance optimization.
Creating new nodes
-
Each node has to inherit from one of the three base classes (LeafNode, CompositeNode, DecoratorNode) and define the ProcessNode function (Fig. 1).
-
Nodes are defined in C++ through a simple API (e.g., AddNodePin(), AddBlackboardPin()) which allows users to construct nodes efficiently (Fig. 2).
-
Serialization and editor integration are handled automatically, so new nodes appear seamlessly (Fig. 3 and 4).
Fig. 1
Fig. 2
Fig. 4

Fig. 3