Agent skill

Unreal Blueprint and C++ Interop

by quodsoler in quodsoler/unreal-engine-skills

Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.

MITAuto-check passedGame Development

Install Unreal Blueprint and C++ Interop

skills CLI
$ npx skills add quodsoler/unreal-engine-skills --skill ue-blueprint-cpp-interop -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install quodsoler/unreal-engine-skills ue-blueprint-cpp-interop --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ue-blueprint-cpp-interop .claude/skills/ue-blueprint-cpp-interop && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ue-blueprint-cpp-interop
GitHub stars
359
Token cost
~7.8k tokens
SKILL.md length
2,206 words
Files
3 (incl. references)
Skills in repo
31
Repo updated
First seen
Licence
MIT

At a glance

Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.

  • Exposing a C++ function or property to Blueprint
  • SKILL.md covers Context, UFUNCTION Exposure, UPROPERTY Exposure and Function Libraries, plus 11 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Writing a custom or async Blueprint node

What it does

Targeting Unreal Engine 5.8, the skill covers the boundary between native code and the Blueprint VM: which UFUNCTION and UPROPERTY specifiers and meta keys produce which node shapes, function libraries, latent and async action nodes, Blueprint-implementable interfaces, delegates, and how C++ calls back into a Blueprint graph. Deprecated forms are listed so they are not used, and ObjectMacros.h is named as the authority for specifiers.

A routing table sends each kind of request to a section, from making a function callable or overridable to subsystems, developer settings and editor-callable buttons. The agent first reads .agents/ue-project-context.md if it exists and asks questions only when two readings would produce different code. The code needs the Core, CoreUObject and Engine modules, plus DeveloperSettings for settings pages. Two reference files cover meta specifiers and node patterns, and related skills handle reflection basics and editor tools.

When your agent uses it

  • Exposing a C++ function or property to Blueprint
  • Writing a custom or async Blueprint node
  • Calling Blueprint events or interfaces from native code
  • Adding a BlueprintAssignable delegate for Blueprint binding

Example prompts

  • “Expose this health component's damage function to Blueprint as a BlueprintCallable node.”
  • “Create an async Blueprint node that finishes with success and failure exec pins.”

Requirements

  • An Unreal Engine C++ project
  • Optionally the project context file at .agents/ue-project-context.md

What it can do on your machine

Read from SKILL.md and the folder at commit f3742d7. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Unreal Blueprint and C++ Interop loads about 7.8k tokens when it runs, and up to ~15k if it reads all its reference files. Until then it costs about 185 tokens; SKILL.md has 2,206 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~185
When it runs · the whole SKILL.md, loaded when a task matches
~7.8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~15k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 2,206 words, ~7,840 tokens.

Download SKILL.mdSave it as .claude/skills/ue-blueprint-cpp-interop/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
ue-blueprint-cpp-interop
description
Use when exposing C++ to Blueprint or calling Blueprint from C++: UFUNCTION(BlueprintCallable), BlueprintPure, BlueprintImplementableEvent, BlueprintNativeEvent, _Implementation, UBlueprintFunctionLibrary, WorldContext, DefaultToSelf, ExpandEnumAsExecs, DeterminesOutputType, latent nodes, FPendingLatentAction, FLatentActionInfo, UBlueprintAsyncActionBase, BlueprintAssignable, UINTERFACE, Execute_, TScriptInterface, UENUM(BlueprintType), CallInEditor, FindFunction, ProcessEvent. Also use when the user mentions 'expose to Blueprint', 'custom Blueprint node', 'async Blueprint node' or 'meta specifier'. For reflection and container basics, see ue-cpp-foundations; for details customization, see ue-editor-tools.
metadata.version
2.0.0
metadata.engine
5.8

UE Blueprint / C++ Interop

Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".

This skill covers the boundary between native code and the Blueprint VM: which UFUNCTION/UPROPERTY specifiers and meta= keys produce which node shapes, function libraries, latent and async nodes, Blueprint-implementable interfaces, and how C++ calls back into a Blueprint graph. Everything here lives in Core, CoreUObject and Engine (PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine" });); Project Settings pages also need DeveloperSettings. The authority for every specifier is Runtime/CoreUObject/Public/UObject/ObjectMacros.h — anything not declared in its UC, UI, UF, UP, US or UM enumerations is not a specifier.

Context

Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.

Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.

Request is about…Go to
Making a C++ function callable or overridable in BlueprintUFUNCTION Exposure
Making data visible or editable in Blueprint, getters/settersUPROPERTY Exposure
Static helpers, WorldContext, DefaultToSelfFunction Libraries
A node with an exec pin that finishes later (Delay-style)Latent Nodes
A node with several output exec pins that fire on eventsAsync Action Nodes
Interfaces Blueprint can implement, Execute_, TScriptInterfaceBlueprint Interfaces
UENUM, USTRUCT, containers as Blueprint typesEnums and Structs in Blueprint
BlueprintAssignable events, binding Blueprint to a C++ delegateDelegates and Events
Running Blueprint logic from native code, Blueprint classesCalling Blueprint from Native Code
Subsystems, UDeveloperSettings, Exec commandsSubsystems and Settings in Blueprint
A button in the Details panel, editor-only actionsEditor-Callable Functions

UFUNCTION Exposure

SpecifierNode shapeC++ body
BlueprintCallableExec pins in and outYours
BlueprintPureNo exec pins; implies BlueprintCallableYours, side-effect free
BlueprintImplementableEventEvent the Blueprint implementsNone — UHT generates the thunk
BlueprintNativeEventEvent the Blueprint may overrideName_Implementation only
BlueprintGetter / BlueprintSetterHidden; reached through the propertyYours
BlueprintAuthorityOnlyBlueprint calls are skipped without network authority (direct C++ calls still run)Yours
BlueprintCosmeticBlueprint calls are skipped on a dedicated server (direct C++ calls still run)Yours
BlueprintInternalUseOnlyNot offered in the palette; only generated nodes call itYours
CallInEditorButton on the Details panelYours
ExecConsole commandYours

Category="A\|B" builds a nested palette category. The node-shaping meta= keys — DisplayName, ToolTip, Keywords, CompactNodeTitle, AdvancedDisplay, ReturnDisplayName, HidePin, DeterminesOutputType, DynamicOutputParam, ArrayParm, ExpandEnumAsExecs, WorldContext, UnsafeDuringActorConstruction, DevelopmentOnly, BlueprintThreadSafe and the rest — are tabled with header citations in references/blueprint-meta-specifiers.md.

cpp
// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS(Blueprintable)
class MYGAME_API AMyActor : public AActor
{
    GENERATED_BODY()
public:
    UFUNCTION(BlueprintCallable, Category="MyGame|Combat", meta=(Keywords="damage hurt"))
    void ApplyDamage(float Amount);

    UFUNCTION(BlueprintPure, Category="MyGame|Combat", meta=(CompactNodeTitle="HP", ReturnDisplayName="Health"))
    float GetHealth() const;

    /** Blueprint supplies the whole body; C++ never defines this. */
    UFUNCTION(BlueprintImplementableEvent, Category="MyGame|Combat")
    void OnDamaged(float Amount);

    /** C++ supplies the default in OnDied_Implementation; Blueprint may override it. */
    UFUNCTION(BlueprintNativeEvent, Category="MyGame|Combat")
    void OnDied();
    virtual void OnDied_Implementation();

    UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="MyGame|Combat")
    void ResetOnServer() { Health = MaxHealth; }     // Blueprint calls skipped on clients

    UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="MyGame|FX")
    void PlayHitFlash() {}                           // Blueprint calls skipped on a dedicated server

    UFUNCTION(CallInEditor, Category="MyGame|Tools")
    void SnapToGround() {}                           // button in the Details panel

private:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="MyGame|Combat", meta=(AllowPrivateAccess="true", ClampMin="0.0"))
    float Health = 100.f;

    float MaxHealth = 100.f;
};
cpp
// MyActor.cpp
#include "MyActor.h"

void AMyActor::ApplyDamage(float Amount)
{
    Health = FMath::Max(0.f, Health - Amount);
    OnDamaged(Amount);                  // runs the Blueprint graph
    if (Health <= 0.f) { OnDied(); }    // runs the BP override if any, else OnDied_Implementation
}

float AMyActor::GetHealth() const { return Health; }
void AMyActor::OnDied_Implementation() {}            // the C++ default, overridable in Blueprint

Raise an event by its plain name (OnDied()), never OnDied_Implementation() — the plain name is the generated thunk that dispatches to Blueprint. A subclass overrides virtual void OnDied_Implementation() override; and chains with Super::OnDied_Implementation();, never Super::OnDied();.

Parameters and pins
C++ parameterBlueprint pin
float AmountInput
const FVector& BaseInput, passed by reference
FVector& OutOutput pin, not an input
UPARAM(ref) FVector& InOutBy-reference input that is also an output
UPARAM(DisplayName="Event") FMyReadySignature CallbackInput renamed on the node

A bare T& gets the OutParm flag from UHT; UPARAM(ref) adds ReferenceParm so the pin stays an input. meta=(AutoCreateRefTerm="Offset") gives a reference input an inline literal when nothing is connected.

UPROPERTY Exposure

SpecifierEffect in Blueprint
BlueprintReadWriteGet and Set nodes
BlueprintReadOnlyGet node only
BlueprintGetter=FnGet routes through UFUNCTION(BlueprintGetter)
BlueprintSetter=FnSet routes through UFUNCTION(BlueprintSetter); implies BlueprintReadWrite
BlueprintAssignableBind Event node (multicast dynamic delegates only)
BlueprintCallableBroadcast node (multicast dynamic delegates only)
BlueprintAuthorityOnlyDelegate accepts only BlueprintAuthorityOnly events

BlueprintReadWrite/BlueprintReadOnly on a private member is a UHT error ("BlueprintReadWrite should not be used on private members") unless the property carries meta=(AllowPrivateAccess="true"). An editor-only property cannot be a Blueprint-exposed struct member. Editor meta= keys (ClampMin/ClampMax, UIMin/UIMax, EditCondition, EditConditionHides, InlineEditConditionToggle, TitleProperty, ShowOnlyInnerProperties, MultiLine, GetOptions, AllowedClasses, MustImplement, Categories, Bitmask/BitmaskEnum, ExposeOnSpawn): references/blueprint-meta-specifiers.md.

C++ member typeBlueprint pin
double / floatReal
TObjectPtr<UStaticMesh>Object reference
TSubclassOf<AActor>Class (filtered by meta=(MustImplement=…), AllowedClasses, BlueprintBaseOnly)
TSoftObjectPtr<T> / TSoftClassPtr<T>Soft reference; Blueprint resolves or loads on demand
FInstancedStructStruct pin whose concrete type is chosen in the editor
TScriptInterface<IMyInteractable>Interface reference
FMyHealthChangedSignature (multicast dynamic)Bind Event / Broadcast nodes via BlueprintAssignable
FTimerHandleUSTRUCT(BlueprintType) handle passed straight through

A worked component showing ExposeOnSpawn, EditCondition/EditConditionHides, InlineEditConditionToggle, MustImplement and a BlueprintGetter/BlueprintSetter pair: references/blueprint-meta-specifiers.md.

Floats and doubles. Both float and double properties show as a Blueprint Real pin (UEdGraphSchema_K2 maps FFloatProperty and FDoubleProperty to PC_Real with sub-category PC_Float/PC_Double), and Blueprint-authored variables are doubles. Declare double for scalars that flow through Blueprint math so no narrowing conversion is inserted; keep float only where the engine type is already float.

Function Libraries

UBlueprintFunctionLibrary (Kismet/BlueprintFunctionLibrary.h) is UCLASS(Abstract) and every member is static. GetWorld() returns null on its CDO, so take const UObject* WorldContextObject, tag it meta=(WorldContext="WorldContextObject") and resolve with GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); meta=(DefaultToSelf="Param") pre-wires a pin to the calling object.

cpp
// MyBlueprintLibrary.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Templates/SubclassOf.h"
#include "MyBlueprintLibrary.generated.h"

class AActor;

UENUM(BlueprintType)
enum class EMyConsumeResult : uint8
{
    Consumed,
    NotEnough
};

UCLASS()
class MYGAME_API UMyBlueprintLibrary : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()
public:
    /** WorldContextObject is hidden on the node and filled in by the graph. */
    UFUNCTION(BlueprintCallable, Category="MyGame|Utility", meta=(WorldContext="WorldContextObject"))
    static int32 CountPawns(const UObject* WorldContextObject);

    /** The return pin takes the type plugged into ActorClass, so Blueprint needs no cast. */
    UFUNCTION(BlueprintPure, Category="MyGame|Utility", meta=(DefaultToSelf="Target", DeterminesOutputType="ActorClass"))
    static AActor* FindAttachedActorOfClass(AActor* Target, TSubclassOf<AActor> ActorClass);

    /** One input enum becomes one output exec pin per enumerator. */
    UFUNCTION(BlueprintCallable, Category="MyGame|Utility", meta=(ExpandEnumAsExecs="Result"))
    static void TryConsume(int32 Available, int32 Amount, EMyConsumeResult& Result);
};

The matching .cpp: references/blueprint-node-patterns.md. ExpandEnumAsExecs accepts exactly one input parameter (UHT errors on a second); name ReturnValue to expand the return value, and use ExpandBoolAsExecs for a bool. Wildcard array nodes use meta=(ArrayParm="Items", ArrayTypeDependentParams="Item").

Latent Nodes

A latent node holds one exec pin pending across frames. It needs meta=(Latent, LatentInfo="LatentInfo", WorldContext="WorldContextObject") and a trailing FLatentActionInfo parameter, plus an FPendingLatentAction subclass registered with the world's FLatentActionManager. UKismetSystemLibrary::Delay and FDelayAction (Engine/Public/DelayAction.h) are the engine reference.

cpp
// MyLatentLibrary.h — declaration
UFUNCTION(BlueprintCallable, Category="MyGame|Flow", meta=(Latent, LatentInfo="LatentInfo", WorldContext="WorldContextObject", Duration="1.0"))
static void WaitSeconds(const UObject* WorldContextObject, float Duration, FLatentActionInfo LatentInfo);
cpp
// MyLatentLibrary.cpp — the UUID guard is mandatory
void UMyLatentLibrary::WaitSeconds(const UObject* WorldContextObject, float Duration, FLatentActionInfo LatentInfo)
{
    if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
    {
        FLatentActionManager& Manager = World->GetLatentActionManager();
        if (Manager.FindExistingAction<FMyWaitAction>(LatentInfo.CallbackTarget, LatentInfo.UUID) == nullptr)
        {
            Manager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, new FMyWaitAction(Duration, LatentInfo));
        }
    }
}

Without the FindExistingAction guard, re-entering the node stacks a second action on the same UUID and the exec pin fires more than once. The action subclass overrides UpdateOperation(FLatentResponse& Response) and finishes with Response.FinishAndTriggerIf(bDone, ExecutionFunction, OutputLink, CallbackTarget), copying ExecutionFunction, Linkage and CallbackTarget out of the FLatentActionInfo in its constructor; it also overrides NotifyObjectDestroyed(), NotifyActionAborted() and, under WITH_EDITOR, GetDescription() const. FLatentResponse additionally offers DoneIf(bool) and TriggerLink(ExecutionFunction, LinkID, CallbackTarget) for several exit links. Complete subclass and the rest of the FLatentActionManager API: references/blueprint-node-patterns.md.

Async Action Nodes

UBlueprintAsyncActionBase (Kismet/BlueprintAsyncActionBase.h) produces a node with one exec input and one output exec pin per BlueprintAssignable delegate. The static factory must carry meta=(BlueprintInternalUseOnly="true") so only the generated node can call it.

cpp
// MyWaitForHealthAction.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "MyWaitForHealthAction.generated.h"

class UMyStatsComponent;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyHealthThresholdSignature, double, Health);

UCLASS()
class MYGAME_API UMyWaitForHealthAction : public UBlueprintAsyncActionBase
{
    GENERATED_BODY()
public:
    UFUNCTION(BlueprintCallable, Category="MyGame|Async", meta=(BlueprintInternalUseOnly="true", WorldContext="WorldContextObject", DisplayName="Wait For Health Below"))
    static UMyWaitForHealthAction* WaitForHealthBelow(UObject* WorldContextObject, UMyStatsComponent* Stats, double Threshold);

    virtual void Activate() override;

    UPROPERTY(BlueprintAssignable)
    FMyHealthThresholdSignature OnReached;      // one output exec pin

    UPROPERTY(BlueprintAssignable)
    FMyHealthThresholdSignature OnFailed;       // a second output exec pin

private:
    UFUNCTION()
    void HandleHealthChanged(double NewHealth);   // AddDynamic targets must be UFUNCTIONs

    UPROPERTY()
    TObjectPtr<UMyStatsComponent> TrackedStats;

    double ThresholdValue = 0.0;
};

The factory does NewObject<UMyWaitForHealthAction>(), stores its inputs, calls RegisterWithGameInstance(WorldContextObject) and returns the action; the node then binds the delegates and calls Activate(), where the work starts. Each completion path broadcasts once and calls SetReadyToDestroy(). An unregistered action lives only for the frame it was created on (RF_StrongRefOnFrame), so a delegate firing later finds it collected. The engine ensures when more than bp.MaxAsyncActionCount (default 10000) actions are alive at once.

UCancellableAsyncAction (Engine/CancellableAsyncAction.h, UCLASS(Abstract, BlueprintType, meta=(ExposedAsyncProxy=AsyncAction))) adds Cancel(), IsActive() const and ShouldBroadcastDelegates() const so the node hands the object back for later cancelling; guard every broadcast with ShouldBroadcastDelegates(). Full Activate/Cancel implementations: references/blueprint-node-patterns.md.

Blueprint Interfaces

UINTERFACE's own specifiers (UI::) are MinimalAPI, Blueprintable, NotBlueprintable and ConversionRoot plus meta=; UHT's shared BlueprintType is also accepted, and engine interfaces use it so the interface is usable as a Blueprint variable type. Blueprint can implement BlueprintImplementableEvent and BlueprintNativeEvent members; a plain virtual C++ method is invisible to Blueprint.

cpp
// MyInteractable.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "MyInteractable.generated.h"

class AActor;

UINTERFACE(Blueprintable, BlueprintType, MinimalAPI)
class UMyInteractable : public UInterface
{
    GENERATED_BODY()
};

class MYGAME_API IMyInteractable
{
    GENERATED_BODY()
public:
    /** Blueprint-only implementations are allowed; C++ implementers write Interact_Implementation. */
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="MyGame|Interaction")
    bool Interact(AActor* Interactor);
    virtual bool Interact_Implementation(AActor* Interactor);

    virtual float GetInteractRange() const { return 200.f; }   // native-only: invisible to Blueprint
};
cpp
// Calling an interface that may be implemented in C++ or in Blueprint
bool MyTryInteract(UObject* Target, AActor* Interactor)
{
    return Target && Target->Implements<UMyInteractable>()
        && IMyInteractable::Execute_Interact(Target, Interactor);
}
FormC++ implementersBlueprint implementers
IMyInteractable::Execute_Interact(Obj, …)YesYes — always use this
Obj->Implements<UMyInteractable>()YesYes
Obj->GetClass()->ImplementsInterface(UMyInteractable::StaticClass())YesYes
Cast<IMyInteractable>(Obj) then a direct callYesNo — the cast returns null
TScriptInterface<IMyInteractable> memberYesInterface pointer is null; still call through Execute_

TScriptInterface<T> (UObject/ScriptInterface.h) stores the object and the interface pointer together and is documented as useful for native interfaces only. Declare UPROPERTY(EditAnywhere, BlueprintReadWrite) TScriptInterface<IMyInteractable> Target; so designers get a filtered picker, and still dispatch with Execute_.

Enums and Structs in Blueprint

cpp
// MyTypes.h
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "MyTypes.generated.h"

UENUM(BlueprintType)
enum class EMyWeaponState : uint8      // BlueprintType enums must be uint8-based
{
    Idle,
    Firing      UMETA(DisplayName="Firing Weapon"),
    Reloading,
    MAX         UMETA(Hidden)
};

USTRUCT(BlueprintType)
struct MYGAME_API FMyWeaponStats
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon")
    double BaseDamage = 10.0;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon")
    TArray<FName> Tags;                // container of a Blueprint-supported type

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon")
    TMap<FName, double> Modifiers;     // key and value must both be Blueprint-supported
};

USTRUCT(BlueprintType)
struct MYGAME_API FMyWeaponRow : public FTableRowBase   // data table row type
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon")
    FMyWeaponStats Stats;
};
  • UENUM(BlueprintType) requires enum class : uint8; UHT rejects any other base ("Invalid BlueprintType enum base - currently only uint8 supported"). UMETA(DisplayName="…") renames an enumerator and UMETA(Hidden) hides it from pickers.
  • USTRUCT(BlueprintType) gives Make and Break nodes. Structs cannot hold UFUNCTIONs — put struct helpers in a function library.
  • No nested containers. TArray, TSet and TMap clear their own "can be a container key/value" capability in UHT, so TArray<TArray<int32>> and TMap<FName, TArray<int32>> do not compile. Wrap the inner container in a USTRUCT.
  • A container is Blueprint-exposable only when its element type — and for TMap its key type — is itself Blueprint-supported.
  • FTableRowBase (Engine/DataTable.h) is USTRUCT(BlueprintInternalUseOnly); derive row structs from it and mark the derived struct BlueprintType. Table loading and row lookup: ue-data-assets-tables.
  • FInstancedStruct (StructUtils/InstancedStruct.h) is USTRUCT(BlueprintType) and gives Blueprint a single pin whose concrete struct type is chosen in the editor; TInstancedStruct<FMyBase> is the typed C++ wrapper.
Show full SKILL.md (880 more words)Show less

Delegates and Events

Only dynamic delegates cross the Blueprint boundary. Declaration macros and native binding rules: ue-cpp-foundations.

  • UPROPERTY(BlueprintAssignable) on a multicast dynamic delegate gives Blueprint a Bind Event node; adding BlueprintCallable also gives it a Broadcast node. Both are legal only on multicast dynamic delegates.
  • Delegate parameters need names — they become the pin names on the event node.
  • Any C++ handler bound with AddDynamic must be a UFUNCTION(); otherwise the name lookup fails at runtime and the handler never runs.
  • A single dynamic delegate (DECLARE_DYNAMIC_DELEGATE, DECLARE_DYNAMIC_DELEGATE_OneParam, …) works as a UFUNCTION parameter, which is how async nodes take a one-shot callback: UPARAM(DisplayName="Event") FMyReadySignature Callback.
  • Native (non-dynamic) delegates cannot be exposed at all; wrap them in a dynamic delegate or an async action.

Calling Blueprint from Native Code

NeedUse
A hook the designer fills inUFUNCTION(BlueprintImplementableEvent), called by its plain name
A hook with a C++ defaultUFUNCTION(BlueprintNativeEvent), called by its plain name
Fire an event many graphs listen toUPROPERTY(BlueprintAssignable) multicast, Broadcast(...)
Call a function that exists only in a Blueprint assetFindFunction + ProcessEvent
Read defaults off a Blueprint classTSubclassOf<T>::GetDefaultObject(), UClass::GetDefaultObject<T>()
cpp
// The params struct must match the function's parameter list exactly, in declaration order.
struct FMyOnScoredParams
{
    int32 Points;
    FString Reason;
};

void MyNotifyScored(UObject* Target, int32 Points)
{
    if (!Target) { return; }

    if (UFunction* Func = Target->FindFunction(FName(TEXT("OnScored"))))
    {
        checkf(Func->ParmsSize == sizeof(FMyOnScoredParams), TEXT("OnScored signature changed"));
        FMyOnScoredParams Params;
        Params.Points = Points;
        Params.Reason = TEXT("Kill");
        Target->ProcessEvent(Func, &Params);
    }
}

FindFunction returns null when the Blueprint was renamed or recompiled away, so always branch on it (FindFunctionChecked asserts instead). Prefer a BlueprintImplementableEvent declaration whenever C++ owns the contract — it is type-checked at compile time.

cpp
// SpawnClassPath is a UPROPERTY(EditDefaultsOnly) TSoftClassPtr<AMyActor> set to BP_MyThing
void MyInspectSpawnClass(const TSoftClassPtr<AMyActor>& SpawnClassPath)
{
    if (UClass* LoadedClass = SpawnClassPath.LoadSynchronous())
    {
        const AMyActor* Defaults = LoadedClass->GetDefaultObject<AMyActor>();
        const bool bIsBlueprintClass = Cast<UBlueprintGeneratedClass>(LoadedClass) != nullptr;   // UClass hides IsA (Class.h:4853)
        UE_LOG(LogMyGame, Log, TEXT("Default health %.1f, Blueprint class %d"), Defaults->GetHealth(), bIsBlueprintClass ? 1 : 0);
    }
}

LoadSynchronous blocks the game thread; for streamed loads use the Asset Manager (ue-data-assets-tables). UBlueprintGeneratedClass (Engine/BlueprintGeneratedClass.h) is the runtime UClass a compiled Blueprint produces — test for it when native and Blueprint classes must be handled differently.

Subsystems and Settings in Blueprint

  • Every UGameInstanceSubsystem, UWorldSubsystem, ULocalPlayerSubsystem and UEngineSubsystem subclass automatically gets a Get <Subsystem> node (UK2Node_GetSubsystem); its BlueprintCallable members then appear on that object. No extra specifier is needed. Subsystem lifetimes and native accessors: ue-cpp-foundations.
  • UDeveloperSettings (Engine/DeveloperSettings.h, module DeveloperSettings) auto-registers a Project Settings page. Declare it UCLASS(Config=Game, DefaultConfig, meta=(DisplayName="My Game")), mark fields UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category=…), and add a UFUNCTION(BlueprintPure) static accessor returning GetDefault<UMyGameSettings>() — Blueprint has no node for GetDefault. GetContainerName(), GetCategoryName() and GetSectionName() are overridable to move the page.
  • UFUNCTION(Exec) declares a console command; the console routes to PlayerInput, PlayerController, Pawn, HUD, GameMode, CheatManager, GameState, PlayerCameraManager and GameInstance. meta=(DevelopmentOnly) compiles a BlueprintCallable out of Shipping, as UKismetSystemLibrary::PrintString does.

Editor-Callable Functions

CallInEditor — see AMyActor::SnapToGround above — is a UFUNCTION specifier, not a meta= key, and the function takes no parameters. It runs against the editor world, so guard anything that assumes PIE. Details customizations, editor utility widgets and asset actions: ue-editor-tools.

Deprecated — do not use

Do not emitUse in 5.8Source
meta=(HideAssetPicker)meta=(HidePinAssetPicker)UE_DEPRECATED(5.6) in UObject/ObjectMacros.h:1673
Delegate.ProcessMulticastDelegate<UObject>(Params)Delegate.ProcessDelegate<UObject>(Params)UE_DEPRECATED(5.8) in UObject/ScriptDelegates.h:1462
SomeClass->ClassDefaultObjectGetDefault<T>(), UClass::GetDefaultObject<T>()UE_DEPRECATED(5.6) in UObject/Class.h:4045
GENERATED_UCLASS_BODY(), GENERATED_IINTERFACE_BODY()GENERATED_BODY()Legacy aliases in UObject/ObjectMacros.h:802-805
Cast<IMyInterface>(Obj)->Foo() on a Blueprint implementerIMyInterface::Execute_Foo(Obj, …)Blueprint implementers have no IMyInterface pointer (UObject/ScriptInterface.h:135)
Obj->Foo_Implementation() to raise a BlueprintNativeEventObj->Foo()The plain name is the generated dispatch thunk (UObject/ObjectMacros.h:997)
A C++ body for a BlueprintImplementableEventDeclare it and stopUHT generates the body (UObject/ObjectMacros.h:992)
UPROPERTY(BlueprintReadWrite) on a private memberAdd meta=(AllowPrivateAccess="true"), or make it protectedUHT error "BlueprintReadWrite should not be used on private members"
UENUM(BlueprintType) enum class EMyState : uint32enum class EMyState : uint8UHT error "Invalid BlueprintType enum base - currently only uint8 supported"
TArray<TArray<T>> or TMap<K, TArray<V>> in a UPROPERTYWrap the inner container in a USTRUCTTArray/TMap clear CanBeContainerValue/CanBeContainerKey in UHT
AddNewAction without a FindExistingAction guardCheck LatentInfo.UUID firstEngine/LatentActionManager.h:121,143
NewObject<UMyAsyncAction>() returned without registeringRegisterWithGameInstance(WorldContextObject)Kismet/BlueprintAsyncActionBase.h:37

Common Mistakes

BlueprintNativeEvent without _Implementation, or a C++ body for a BlueprintImplementableEvent: the first is an unresolved external, the second a duplicate symbol (UHT already emitted one). A native event needs virtual void Foo_Implementation(...) defined; an implementable event needs no definition at all.

BlueprintPure with side effects: the compiler prunes unused pure nodes and re-evaluates the rest at each consumer, so the side effect runs an unpredictable number of times. Use BlueprintCallable.

A non-const reference parameter that was meant as an input:

cpp
static void Scale(FVector& Value, double Factor);                 // WRONG: Value becomes an output pin
static void Scale(UPARAM(ref) FVector& Value, double Factor);     // RIGHT: by-reference input
static void Scale(const FVector& Value, double Factor);           // RIGHT: plain input

A library function that needs the world but declares no WorldContext: GetWorld() returns null on a UBlueprintFunctionLibrary CDO. Take const UObject* WorldContextObject, tag it meta=(WorldContext="WorldContextObject") and resolve with GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull).

BlueprintReadWrite on a private member: a UHT error, not a warning. Add meta=(AllowPrivateAccess="true").

Nested containers in a UPROPERTY: UHT rejects TArray<TArray<T>> and TMap<K, TArray<V>>. Wrap the inner container in a USTRUCT(BlueprintType).

A latent action added without the UUID guard: re-entering the node stacks duplicate actions and the completion pin fires once per copy. Check FindExistingAction<FMyWaitAction>(LatentInfo.CallbackTarget, LatentInfo.UUID) first.

An async action collected mid-flight: an action that never calls RegisterWithGameInstance lives only for the frame it was created on, so a delegate firing later never reaches it. Register in the factory and call SetReadyToDestroy() exactly once when finished.

Cast<IMyInterface>(Obj) on a Blueprint implementer: returns null and the call is silently skipped. Test with Obj->Implements<UMyInterface>() and dispatch with IMyInterface::Execute_Foo(Obj, …).

A static async factory without meta=(BlueprintInternalUseOnly="true"): Blueprint offers both the proxy node and a bare call to the factory, and the bare call returns an object nothing ever activates.

  • ue-cpp-foundations — UCLASS/UPROPERTY/UFUNCTION fundamentals, containers, delegates, subsystem lifetimes, GC
  • ue-actor-component-architecture — Actor and component lifecycle, spawning, BlueprintSpawnableComponent
  • ue-gameplay-framework — GameMode, PlayerController, damage, the classes Blueprint most often extends
  • ue-editor-tools — details customization, editor utility widgets, asset actions, editor subsystems
  • ue-async-threading — AsyncTask, UE::Tasks, timers and thread safety behind an async node
  • ue-data-assets-tables — UDataAsset, DataTable rows, soft references and Asset Manager loading
  • ue-ui-umg-slate — UUserWidget C++ bases, BindWidget, exposing widget data to Blueprint

© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files (references) in skills/ue-blueprint-cpp-interop of quodsoler/unreal-engine-skills.

  • SKILL.md
  • references/blueprint-meta-specifiers.md
  • references/blueprint-node-patterns.md

Open the folder on GitHubat commit f3742d7

Compare with similar skills

Unreal Blueprint and C++ Interop next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Unreal Blueprint and C++ Interop compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Unreal Blueprint and C++ Interop this skillquodsoler/unreal-engine-skills359—~7.8kAutomated safety check: PassMIT
Unreal Engine MCPEpicGames/unreal-engine-skills-for-claude-code-plugin327—~1.8kAutomated safety check: PassMIT
Unreal Live CodingItalink/UnrealClientProtocol127—~1kAutomated safety check: PassMIT
Unreal Cpp Gameplayukanwat/overtime3871 repos~1.5kAutomated safety check: PassApache-2.0
Unreal Enhanced Inputukanwat/overtime3871 repos~1.5kAutomated safety check: PassApache-2.0
Unreal Niagaraukanwat/overtime3871 repos~1.5kAutomated safety check: PassApache-2.0

Similar skills

  • Unreal Engine MCP

    EpicGames/unreal-engine-skills-for-claude-code-plugin

    Drives a live Unreal Editor through the unreal-mcp server: spawn actors, edit Blueprints, materials and sequences, change properties and trigger Live Coding.

    327 GitHub stars~1.8k tokensUpdated 21 days ago
    Game DevelopmentAuto-check passed
  • Unreal Live Coding

    Italink/UnrealClientProtocol

    Trigger Live Coding compilation via UCP. An agent skill from Italink/UnrealClientProtocol.

    127 GitHub stars~1k tokensUpdated 1 mo ago
    Game DevelopmentAuto-check passed
  • Unreal Cpp Gameplay

    ukanwat/overtime

    Write Unreal Engine 5 C++ gameplay code: the UCLASS/UPROPERTY/UFUNCTION reflection macros, the Gameplay Framework (GameMode, Pawn, Character, PlayerController, Actor components), and the module…

    387 GitHub starsUsed in 1 repo~1.5k tokens
    Game DevelopmentAuto-check passed
  • Unreal Enhanced Input

    ukanwat/overtime

    Set up player input in Unreal Engine 5 with Enhanced Input: Input Actions, Input Mapping Contexts, modifiers and triggers, adding the mapping context, and binding actions by ETriggerEvent.

    387 GitHub starsUsed in 1 repo~1.5k tokens
    Game DevelopmentAuto-check passed
  • Unreal Niagara

    ukanwat/overtime

    Create and control VFX in Unreal Engine 5 with Niagara: systems and emitters, modules and the spawn/update stages, exposed User parameters, and spawning or driving effects from Blueprints or C++.

    387 GitHub starsUsed in 1 repo~1.5k tokens
    Game DevelopmentAuto-check passed
  • Scenario Unreal Gameplay

    scenario-labs/skills

    A skill your agent uses when building or debugging UE5 gameplay: a character with double jump or dash, abilities with cooldowns, enemy AI that patrols, chases and attacks, a health bar or HUD…

    913 GitHub stars~5.2k tokensUpdated 2 days ago
    Game DevelopmentAuto-check passed

More from quodsoler/unreal-engine-skills

All 31 skills in this repo
  • Unreal Actor-Component Architecture

    quodsoler/unreal-engine-skills

    Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.

    359 GitHub stars~7.5k tokensUpdated 10 days ago
    Auto-check passed
  • Unreal Engine AI and Navigation

    quodsoler/unreal-engine-skills

    Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.

    359 GitHub stars~8.9k tokensUpdated 10 days ago
    Auto-check passed
  • Unreal Engine Animation System

    quodsoler/unreal-engine-skills

    Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.

    359 GitHub stars~7k tokensUpdated 10 days ago
    Auto-check passed
  • Unreal Engine Async and Threading

    quodsoler/unreal-engine-skills

    Picks and applies the right Unreal Engine C++ concurrency API, from UE::Tasks and FPipe to ParallelFor, FRunnable, locks and timers, with game-thread safety rules.

    359 GitHub stars~8k tokensUpdated 10 days ago
    Auto-check passed
  • Ue Audio System

    quodsoler/unreal-engine-skills

    A skill your agent uses when playing, mixing or debugging sound in Unreal Engine — one-shot SFX, looping ambience, music, dialogue or procedural audio.

    359 GitHub stars~7.9k tokensUpdated 10 days ago
    Auto-check passed
  • Unreal Character Movement Component

    quodsoler/unreal-engine-skills

    Reference for writing and debugging UCharacterMovementComponent code in Unreal Engine C++: custom movement modes, floor detection, root motion, prediction and gravity.

    359 GitHub stars~8.5k tokensUpdated 10 days ago
    Auto-check passed

Questions about Unreal Blueprint and C++ Interop

What does Unreal Blueprint and C++ Interop do?

Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces. 8, the skill covers the boundary between native code and the Blueprint VM: which UFUNCTION and UPROPERTY specifiers and meta keys produce which node shapes, function libraries, latent and async action nodes, Blueprint-implementable interfaces, delegates, and how C++ calls back into a Blueprint graph.h is named as the authority for specifiers.

When should I use Unreal Blueprint and C++ Interop?

Unreal Blueprint and C++ Interop fits situations like: exposing a C++ function or property to Blueprint; writing a custom or async Blueprint node; calling Blueprint events or interfaces from native code; adding a BlueprintAssignable delegate for Blueprint binding.

How do I install Unreal Blueprint and C++ Interop in Claude Code?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-blueprint-cpp-interop -a claude-code`. Or copy the skill folder (skills/ue-blueprint-cpp-interop in quodsoler/unreal-engine-skills) into .claude/skills/ue-blueprint-cpp-interop in your project. Claude Code loads it when a task matches its description.

How do I install Unreal Blueprint and C++ Interop in Codex?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-blueprint-cpp-interop -a codex`. Or copy the skill folder (skills/ue-blueprint-cpp-interop in quodsoler/unreal-engine-skills) into .agents/skills/ue-blueprint-cpp-interop in your project. Codex loads it when a task matches its description.

Can I use Unreal Blueprint and C++ Interop in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add quodsoler/unreal-engine-skills --skill ue-blueprint-cpp-interop -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ue-blueprint-cpp-interop, .gemini/skills/ue-blueprint-cpp-interop, .github/skills/ue-blueprint-cpp-interop and .opencode/skills/ue-blueprint-cpp-interop in your project.

What does Unreal Blueprint and C++ Interop need to run?

SKILL.md names no scripts, command-line tools or credentials: Unreal Blueprint and C++ Interop is instructions for the agent only. Our summary lists: An Unreal Engine C++ project; Optionally the project context file at .agents/ue-project-context.md.

Does Unreal Blueprint and C++ Interop access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Unreal Blueprint and C++ Interop safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Unreal Blueprint and C++ Interop use?

Unreal Blueprint and C++ Interop is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Unreal Blueprint and C++ Interop use?

About 7.8k tokens (SKILL.md is roughly 31k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 7.4k tokens, read only when the agent opens those files.

What are the alternatives to Unreal Blueprint and C++ Interop?

Skills that share tags, products or a category with Unreal Blueprint and C++ Interop: Unreal Engine MCP (EpicGames/unreal-engine-skills-for-claude-code-plugin, 327 stars), Unreal Live Coding (Italink/UnrealClientProtocol, 127 stars), Unreal Cpp Gameplay (ukanwat/overtime, 387 stars) and Unreal Enhanced Input (ukanwat/overtime, 387 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Unreal Blueprint and C++ Interop?

quodsoler (a GitHub user) maintains it in quodsoler/unreal-engine-skills, which has 359 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on September 28, 2026.

Source: quodsoler/unreal-engine-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.