Any kind of split between the three can work, however below are some suggestions that can help in choosing what approach to take.
What logic goes into pawn
Unreal’s own terminology for Pawn and Controller should give some hints.
Pawns usually have some kind of type - f.ex. a dog, an ogre, a tank - and each type has certain things it can do. A dog can bark, an ogre can swing its axe, a tank can rotate its turret.
This means the pawn class should have functions that trigger these kinds of things the pawn can do, and Delegates which you can bind to get notified of the thing finishing. Gameplay Tasks can also be an option, especially for actions that take some amount of time to finish and are commonly used from blueprints. You can also consider using the Gameplay Ability System as part of this.
This approach allows you to clearly define what a certain pawn can do, and makes it easy to use its functionality from things like the AI controller, Beahvior Trees or State Trees.
What logic goes into controller
The controller often acts as a bridge between the pawn and the behavior tree or other AI systems. It can also include other AI-specific parts, such as the AI Perception System.
In other words, the controller usually binds to events in the pawn, and updates the Blackboard. In some cases, the controller can also have more elaborate behaviors defined within its functions, which can help make behavior trees more reusable across different controllers. AITasks can be used in a similar fashion with controllers as Gameplay Tasks are used with pawns.
What logic goes into Behavior Trees
There are two typical ways of using behavior trees: Light tasks and heavy tasks.
- Lightweight Behavior Tree Tasks essentially act as simple proxies. They don’t contain much game logic other than calling functions directly on the pawn or controller.
- Heavy tasks on the other hand contain a larger amount of logic, making more decisions based on information in the blackboard or information directly on the controller or pawn.
Both approaches can be valid depending on how you want to structure the other parts of your system. You can even use both approaches at the same time - some tasks are simpler to implement directly on your pawn, while some may be more convenient to wrap in a BT node.
Benefits of lightweight nodes
Light weight nodes offer the benefit of allowing the behavior tree to be reused more easily, while still allowing you to customize the behavior of each pawn. For example, an attack function on a pawn or controller can be overridden to customize how a particular pawn attacks. If this logic was in your behavior tree, you might need to use a separate tree to customize it.
Light nodes can reduce coupling between your systems, since it can allow the behavior tree to focus on the broad strokes of behavior and sequencing different actions, while the more specific steps of how the actions are performed are controlled elsewhere. This can allow replacing them without having to modify the behavior tree to accommodate for it.
Benefits of heavyweight nodes
Heavier nodes can sometimes reduce the amount of structural complexity in your game. Since you’re already implementing a BT node for some purpose, having more logic inside it can reduce the number of places that need to change if that particular logic changes. However, this can also cause a lot of coupling.
Heavy nodes can also be faster for quickly prototyping functionality, as you can build your logic directly within the node.