【Unreal Engine】Exposing C++ Variables and Functions to Blueprint (UFUNCTION/UPROPERTY)

Created: 2025-12-12

How to use UFUNCTION, UPROPERTY, and UCLASS macros to make C++-defined variables and functions accessible from Blueprint, with concrete code examples.

In Unreal Engine (UE) development, C++ handles performance-critical processing and complex game logic cores, while Blueprint enables rapid prototyping and intuitive logic construction by designers—truly two wheels of the same vehicle.

However, many beginners and intermediate developers face a challenge: "How can I easily and safely call convenient functions and variables written in C++ from Blueprint?" Even if you write efficient C++ code, you can't fully benefit from it if it can't be used from Blueprint.

This article thoroughly explains the core mechanisms for smooth C++ and Blueprint integration, focusing particularly on UFUNCTION and UPROPERTY macros, with concrete code examples and best practices. After reading this, your UE development capabilities will expand dramatically.


Overview of UCLASS, UFUNCTION, and UPROPERTY

To expose C++ code to the Blueprint world, you need to tell Unreal Engine's reflection system about its existence. This role is fulfilled by special macro groups like UCLASS, UFUNCTION, and UPROPERTY.

UCLASS: Registering Classes

First, classes you want to access from Blueprint must have the UCLASS() macro. This indicates that the class should be tracked and managed by UE's reflection system.

// MyActor.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS() // This macro is required
class MYPROJECT_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    AMyActor();
};

UPROPERTY: Exposing Variables

To make C++-defined variables referenceable or editable from Blueprint, add the UPROPERTY() macro. The arguments (specifiers) in this macro provide fine control over Blueprint behavior.

SpecifierMeaningBlueprint Behavior
EditAnywhereEditable from anywhereEditable in Details panel (instance, defaults)
BlueprintReadOnlyRead-only from BlueprintGet value node generated in Blueprint graph
BlueprintReadWriteRead/write from BlueprintGet/Set value nodes generated in Blueprint graph
VisibleAnywhereViewable from anywhereValue reference only in Details panel
Category = "My Category"Display category in Details panelOrganized by category for easier management

Code Example (UPROPERTY):

// MyActor.h
// ...
UCLASS()
class MYPROJECT_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // Variable readable/writable from Blueprint and editable in Details panel
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
    float Health = 100.0f;

    // Read-only variable from Blueprint
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stats")
    int32 MaxAmmo = 30;
};

UFUNCTION: Exposing Functions

To call C++-implemented logic from Blueprint, add the UFUNCTION() macro to the function.

SpecifierMeaningBlueprint Behavior
BlueprintCallableCallable from BlueprintAvailable as standard function node
BlueprintPureCallable as Pure FunctionAvailable as node with no execution pins, only return value (recommended for functions that don't change state)
BlueprintImplementableEventEvent declared in C++, implemented in BlueprintCan be overridden as event node in Blueprint
BlueprintNativeEventHas default C++ implementation, can be overridden in BlueprintCan have implementation in both C++ and Blueprint

Code Example (UFUNCTION):

// MyActor.h
// ...
UCLASS()
class MYPROJECT_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // 1. Function callable from Blueprint
    UFUNCTION(BlueprintCallable, Category = "Combat")
    void ApplyDamageToHealth(float DamageAmount);

    // 2. Pure function callable from Blueprint
    UFUNCTION(BlueprintPure, Category = "Stats")
    float GetHealthPercentage() const;

    // 3. Event implemented in Blueprint
    UFUNCTION(BlueprintImplementableEvent, Category = "Events")
    void OnHealthDepleted();
};

Code Example (UFUNCTION Implementation):

// MyActor.cpp
// ...
void AMyActor::ApplyDamageToHealth(float DamageAmount)
{
    Health = FMath::Max(0.0f, Health - DamageAmount);
    if (Health <= 0.0f)
    {
        // Call Blueprint-implemented event
        OnHealthDepleted();
    }
}

float AMyActor::GetHealthPercentage() const
{
    // Dividing by 100.0f here since MaxHealth isn't defined as UPROPERTY
    return Health / 100.0f;
}

Using from Blueprint

After compiling the above C++ code and returning to the editor, create a Blueprint class inheriting from AMyActor, and the C++-exposed features automatically become available.

Using Variables (UPROPERTY)

  • Details Panel: Variables with EditAnywhere or VisibleAnywhere appear in the "Stats" category of the Blueprint instance's Details panel, where values can be edited or referenced.
  • Graph: Variables with BlueprintReadWrite or BlueprintReadOnly can be searched and used as "Get Health" or "Set Health" nodes from the right-click menu in the Blueprint graph.

Using Functions (UFUNCTION)

  • Calling: The ApplyDamageToHealth function can be searched as "Apply Damage To Health" node from the right-click menu in the Blueprint graph, connected via execution pins and called.

Note on Function Name Conflicts

When defining functions in C++, names like TakeDamage already exist in the AActor class, potentially causing conflicts or unintended overrides. We recommend giving your own features more specific, unique names like ApplyDamageToHealth.

  • Pure Functions: The GetHealthPercentage function can be used without execution pins, connecting the return value pin directly to other nodes.
  • Events: The OnHealthDepleted event can be searched as "Event On Health Depleted" node from the right-click menu in the Blueprint graph, implementing processing when the event occurs.

Best Practices and Common Mistakes

Follow these points to facilitate smooth C++ and Blueprint integration.

Best Practices

  1. Use BlueprintPure: Always specify BlueprintPure for functions that don't change state and simply calculate and return values. This prevents Blueprint graphs from becoming cluttered with execution pins and makes data flow visually clear.
  2. Specify Category: Always specify Category = "..." for UPROPERTY and UFUNCTION. This improves searchability in Blueprint right-click menus and Details panels, keeping things organized.
  3. Separate Logic: Thoroughly implement performance-critical processing and complex algorithms in C++, and leave the timing of calling them and control of parameters designers adjust to Blueprint.

Common Mistakes

  1. Forgetting Macros: Forgetting UCLASS, UFUNCTION, or UPROPERTY macros means they won't be registered with the reflection system and will be completely inaccessible from Blueprint. Especially ensure macros are written in header files and the .generated.h file is properly included.
  2. Argument Types: Using C++ types not supported by Blueprint (e.g., standard library containers) as function arguments or return values will prevent Blueprint nodes from being generated. Use UE-specific types (FString, TArray, TMap, etc.).
  3. Using const: When specifying BlueprintPure for functions that don't change state, it's common practice in C++ to also add the const qualifier. This guarantees the function doesn't change object state, a C++ best practice.

Key Points for C++ and Blueprint Integration

C++ and Blueprint integration in Unreal Engine is achieved through UFUNCTION and UPROPERTY macros.

ElementMacroMain RoleBlueprint Usage
VariablesUPROPERTYRegister variable with reflection system, set Blueprint access permissions.Edit in Details panel, use Get/Set nodes.
FunctionsUFUNCTIONRegister function with reflection system, set how Blueprint calls it.Use as executable node or pure function node.

Mastering this integration maximizes both C++ performance and Blueprint flexibility, enabling efficient, maintainable game development. Start by actively exposing simple C++ features to Blueprint.