Skip to content

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 BlueprintNativeEvent and BlueprintImplementableEvent functions.
  • Read/write UPROPERTYs marked BlueprintReadWrite.
  • Call UFUNCTIONs marked BlueprintCallable.
  • 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:

SomeComponent->OnEffectApplied(Verb);

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.