Reusable Gameplay Behavior with Blueprintable Objects

Gameplay Systems Blueprints

Reusable Gameplay Behavior with Blueprintable Objects

I often want gameplay behavior to be modular, reusable, and easy to author in Blueprint.

A simple example is quest rewards. Rather than hardcoding reward logic directly in a quest class, I may want a quest to own a list of reusable reward behaviors: give an item, set a global flag, spawn an NPC, grant experience, and so on.

I implemented a command-like pattern by packaging gameplay logic into small, swappable UObject classes.

This is not a full implementation of the Command design pattern, which typically involves features like undo/redo which are not relevant to my use case.

Implementation

The base type is a UObject called UCommandBase, with:

UCLASS(BlueprintType, Blueprintable, Abstract, EditInlineNew, DefaultToInstanced)

This makes the class usable as a Blueprint variable type, subclassable in Blueprint, and creatable inline from the editor for authoring per-owner behavior objects. I store these commands in UPROPERTY(Instanced) arrays such as TArray<TObjectPtr<UCommandBase>>, so each owner gets its own configured instances. Example:

UPROPERTY(EditAnywhere, Instanced, Category="Commands")
TArray<TObjectPtr<UCommandBase>> Commands;

The class exposes a method Execute:

UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void Execute(UObject* Context);
virtual void Execute_Implementation(UObject* Context) { /* default behavior, if any */ }

BlueprintNativeEvent allows the behavior to be implemented in C++, overridden in Blueprint, or authored entirely in Blueprint if needed. BlueprintCallable allows the method to be called from Blueprint, which is useful for executing commands from Blueprint-based systems.

The function receives a UObject* context parameter representing the caller or execution environment. It can be the owning quest, item, component, character, or subsystem. Commands may require world access, in which case the context object should have a reliable GetWorld() path. I recommend validating the world context in the Execute implementation rather than assuming it’s always valid.

Concrete subclasses can expose whatever properties they need. A “give item” behavior might expose an item identifier and quantity. A “set flag” behavior might expose a gameplay tag and a boolean value.

Example Use Cases

Quest rewards

A quest can own an array of behavior objects representing its rewards. When the quest completes, it iterates through them and executes each one, passing itself as context. Example reward behaviors could be UCommandGiveItem, UCommandSetFlag, UCommandSpawnActor, etc.

Item consumption

A consumable item can own an array of behavior objects that define what happens when the item is used. When the item is consumed, it executes each command in that array, passing itself as context. Example commands could be UCommandModifyAttribute, UCommandApplyEffect, UCommandPlaySound, etc.

Limitations

I found myself overusing this pattern at first. It’s tempting to reach for it whenever you want to add some logic to a class, but it’s important not to introduce unnecessary indirection.

This approach is most useful when behavior varies significantly between instances and benefits from composition and reuse. It should not replace simple explicit properties. If every consumable item plays a sound when used, a ConsumptionSound property on the base item may be clearer than introducing a separate behavior object just for that.

In addition, in this implementation I treat commands as stateless, fire-and-forget behavior objects. In this implementation, they cannot support ticking, complex lifecycles, or stateful interactions without additional infrastructure. Such features could be added, but I’d be careful about compromising the simplicity of the pattern, which is one of its main advantages.

Finally, this setup needs extra care in networked contexts. These objects may be best treated as server-side execution helpers, with their gameplay results replicated through the relevant gameplay systems rather than relying on the command objects themselves as the replicated abstraction.

More projects

Continue browsing the archive

Plugins / 2025

UI Framework

A reusable UI framework for Unreal Engine, built as a standalone plugin around CommonUI and Lyra-style patterns for screen registration, layer management, modal flows, and UI lifecycle.

Plugins / 2026

Settings System

A flexible and reusable settings plugin for Unreal Engine projects, providing a solid foundation for settings menus, authoring workflows, runtime behavior, and UX considerations.

Tools / 2025

ImGui Debug Tools

A shared ImGui-based debug layer in Unreal Engine 5 that makes new developer-facing tools cheap to add and easy to maintain.