Blueprints overview¶
Blueprint is Unreal's visual scripting layer. From a C++ engineer's seat, the rule is simple: you write the foundation in C++ so designers can extend it in Blueprint without you.
For how Rephrased splits work between C++ and Blueprint, see Blueprints in Rephrased.
What Blueprint actually is¶
A Blueprint asset is a UClass derived from a C++ UCLASS. It can:
- Override
BlueprintNativeEventandBlueprintImplementableEventfunctions. - Read/write
UPROPERTYs markedBlueprintReadWrite. - Call
UFUNCTIONs markedBlueprintCallable. - Add new
UPROPERTYs and event graphs of its own.
A Blueprint cannot add private data the C++ side doesn't know about. Anything Blueprint references in C++ must be reflected.
Exposing a class to Blueprint¶
Marker on the UCLASS:
UCLASS(Blueprintable, BlueprintType)
class REPHRASED_API URuneEffectComponent : public UActorComponent
Blueprintable— Blueprints can subclass this.BlueprintType— Blueprints can use this as a variable type or function parameter.
Most actor base classes get both. Classes that exist only as data carriers can use BlueprintType alone.
BlueprintNativeEvent vs BlueprintImplementableEvent¶
Both let Blueprint override C++. They differ in whether C++ provides a default.
// Native: C++ has a default, Blueprint can replace it
UFUNCTION(BlueprintNativeEvent, Category = "Effect")
void OnEffectApplied(URuneDataAsset* Verb);
virtual void OnEffectApplied_Implementation(URuneDataAsset* Verb);
// Implementable: C++ declares only, Blueprint must implement
UFUNCTION(BlueprintImplementableEvent, Category = "Effect")
void OnDesignerHook();
Use Native for behavior that has a sensible default; use Implementable for hooks intended for designers (no C++ side at all).
The C++ caller still calls the wrapper:
That dispatches to the Blueprint override if the BP has one, otherwise _Implementation. Do not call _Implementation directly from outside — you bypass the Blueprint.
Calling C++ from Blueprint¶
Mark the function BlueprintCallable (with side effects) or BlueprintPure (no side effects, used as a getter):
UFUNCTION(BlueprintCallable, Category = "Rune")
void InitializeRune(URuneDataAsset* Data);
UFUNCTION(BlueprintPure, Category = "Rune")
bool IsCarryingRune() const;
BlueprintPure shows up as a value node with no exec pin — wire it as input to other nodes.
Reading C++ data from Blueprint¶
UPROPERTY specifiers control this:
BlueprintReadWrite— Blueprint can read and assign.BlueprintReadOnly— Blueprint can read only.- (no specifier) — invisible to Blueprint.
Pair with EditAnywhere / EditDefaultsOnly / etc. for the editor-side visibility. They are independent: a property can be EditAnywhere, BlueprintReadOnly (designer can configure it, BP graph can only read it).
Delegates Blueprint can bind to¶
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSlotChanged, ARuneSlot*, Slot);
UPROPERTY(BlueprintAssignable, Category = "Events")
FOnSlotChanged OnSlotChanged;
DYNAMIC and BlueprintAssignable together make a Blueprint-bindable event. Designers see "On Slot Changed" in the event list and can drop nodes onto it.
What Blueprints should not do¶
- Hold the only reference to a tick-critical loop. C++ should drive things that run every frame.
- Reach into private state. If a designer needs something, expose it with the right specifier.
Change history¶
- 2026-05-23 — Gabriel Li — Split generic Blueprint material from Rephrased project track.
- 2026-05-08 — Gabriel Li — Added baseline change history section for weekly wiki maintenance.