Working with Blueprint (BP) in Unreal Engine

How to work with Blueprint (BP) in the Unreal Engine?

Create Blueprint Asset in C++

Following code is possible to use in UBlueprintFunctionLibrary inherited class.

The code below is an analogy of manual creation of assets in the Unreal Engine editor by clicking right mouse button in Content Drawer and selecting an asset to create.

Based on set Parent Class parameter, there's possible to create any type of Blueprint asset (such as Actor, Static mesh Actor, Character, Widget, ChildBlueprint of another Blueprint...) with the C++ code right in the editor.

/**
 * Editor Only - Will not work in packaged build.
 *
 * Create a blueprint asset
 *
 * @param BlueprintPath	Path of the blueprint: "/Game/Folder/MyBp"
 * @param bOutSuccess	If the action was a success or not
 * @param OutInfoMsg	More information about the action's result
 * 
 * @return The created blueprint
 */
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon | Create Blueprint")
static UBlueprint* CreateBlueprint(FString BlueprintPath, TSubclassOf<UObject> ParentClass, bool& bOutSuccess, FString& OutInfoMsg);
#include "AssetRegistry/AssetRegistryModule.h" // AssetRegistry
#include "Kismet2/KismetEditorUtilities.h"// UnrealEd (Editor Only)
#include "KismetCompilerModule.h" // KismetCompiler (Editor Only)

UBlueprint* UExampleClass::CreateBlueprint(FString BlueprintPath, TSubclassOf<UObject> ParentClass, bool& bOutSuccess, FString& OutInfoMsg)
{
  // Make sure an asset doesn't already exist with that path
  if (StaticLoadObject(UObject::StaticClass(), nullptr, *BlueprintPath) != nullptr)
  {
    bOutSuccess = false;
    OutInfoMsg = FString::Printf(TEXT("Create Blueprint Failed - An asset already exists at that location. '%s'"), *BlueprintPath);
    return nullptr;
  }
	
  // Make sure the parent class is valid
  if (!FKismetEditorUtilities::CanCreateBlueprintOfClass(ParentClass))
  {
    bOutSuccess = false;
    OutInfoMsg = FString::Printf(TEXT("Create Blueprint Failed - Parent class is not blueprintable. '%s'"), *BlueprintPath);
    return nullptr;
  }
	
  // Create asset package
  UPackage* Package = CreatePackage(*BlueprintPath);
  if (Package == nullptr)
  {
    bOutSuccess = false;
    OutInfoMsg = FString::Printf(TEXT("Create Blueprint Failed - Failed to create the asset package. Make sure the path is valid. '%s'"), *BlueprintPath);
    return nullptr;
  }

  // Find the blueprint classes to create
  UClass* BpClass = nullptr;
  UClass* BpGenClass = nullptr;
  FModuleManager::LoadModuleChecked<IKismetCompilerInterface>("KismetCompiler").GetBlueprintTypesForClass(ParentClass, BpClass, BpGenClass);

  // Create asset
  UBlueprint* Blueprint = FKismetEditorUtilities::CreateBlueprint(ParentClass, Package, *FPaths::GetBaseFilename(BlueprintPath), BPTYPE_Normal, BpClass, BpGenClass);

  // Register asset
  FAssetRegistryModule::AssetCreated(Blueprint);
  Blueprint->MarkPackageDirty();

  // Return the asset
  bOutSuccess = true;
  OutInfoMsg = FString::Printf(TEXT("Create Blueprint Succeeded - '%s'"), *BlueprintPath);
  return Blueprint;
}
PrivateDependencyModuleNames.AddRange
(
  new string[] 
  { 
    // Default Modules
    "Core", 
    "CoreUObject", 
    "Engine", 

    // New Modules
    "AssetRegistry",

    // New Modules - Editor Only
    "UnrealEd",
    "KismetCompiler",
  }
);

Compile Blueprint asset with C++

/**
 * Editor Only - Will not work in packaged build.
 *
 * Compile a blueprint asset
 *
 * @param BlueprintPath	Path of the blueprint: "/Game/Folder/MyBp"
 * @param OutInfoMsg	More information about the action's result
 * @param return If the action was a success or not
 */
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon | Compile Blueprint")
static void CompileBlueprint(FString BlueprintPath, FString& OutInfoMsg);
#include "Kismet2/KismetEditorUtilities.h" // UnrealEd (Editor Only)
#include "Kismet2/CompilerResultsLog.h" // UnrealEd (Editor Only)

bool UExampleClass::CompileBlueprint(FString BlueprintPath, FString& OutInfoMsg)
{
  // Load blueprint asset
  UBlueprint* Blueprint = Cast<UBlueprint>(StaticLoadObject(UBlueprint::StaticClass(), nullptr, *BlueprintPath));
	
  if (Blueprint == nullptr)
  {
    OutInfoMsg = FString::Printf(TEXT("Compile Blueprint Failed - Path doesn't lead to a valid Blueprint. '%s'"), *BlueprintPath);
    return false;
  }
	
  // Compile blueprint
  FCompilerResultsLog Result;
  FKismetEditorUtilities::CompileBlueprint(Blueprint, EBlueprintCompileOptions::SkipSave, &Result);

  // Format the result
  FString Logs = Result.Messages.Num() > Result.NumWarnings + Result.NumErrors ? "\n--- Logs ---" : "";
  FString Warnings = Result.NumWarnings > 0 ? "\n--- Warnings ---" : "";
  FString Errors = Result.NumErrors > 0 ? "\n--- Errors ---" : "";

  for (TSharedRef<FTokenizedMessage> Message : Result.Messages)
  {
    switch (Message.Get().GetSeverity())
    {
    default:
    case EMessageSeverity::Type::Info:
      Logs += "\n" + Message.Get().ToText().ToString();
      break;
    case EMessageSeverity::Type::Warning:
    case EMessageSeverity::Type::PerformanceWarning:
    	Warnings += "\n" + Message.Get().ToText().ToString();
    	break;
    case EMessageSeverity::Type::Error:
    	Errors += "\n" + Message.Get().ToText().ToString();
    	break;
    }
  }

  // Return the result
  bool bSuccess = Result.NumErrors == 0;
  FString SucceededOrFailed = bSuccess ? "Succeeded" : "Failed";
  FString Messages = Logs + Warnings + Errors;
  OutInfoMsg = FString::Printf(TEXT("Compile Blueprint %s - '%s' %s"), *SucceededOrFailed, *BlueprintPath, *Messages);
  return bSuccess;
}
PrivateDependencyModuleNames.AddRange
(
  new string[] 
  { 
    // Default Modules
    "Core", 
    "CoreUObject", 
    "Engine", 

    // New Modules - Editor Only
    "UnrealEd",
  }
);

Spawn Actor to any Blueprint

AddNodeToBlueprint defined below will be used by functions adding various kind of actors into any blueprint based on its BlueprintPath.

This way of adding any Actor to any Blueprint comes in handy if we need to extend 1 or more Bluperint actors from one place - e.g. during automatization process. If we code a C++ class, from which a blueprint asset is inherited, adding actors to blueprint is easy to do through the common way.

Add a component node to a blueprint asset (Help function)

/**
 * Editor Only - Will not work in packaged build.
 *
 * Add a component node to a blueprint asset
 *
 * @param BlueprintPath Path of the blueprint: "/Game/Folder/MyBp"
 * @param ComponentTemplate The component to use as a template when creating the node
 * @param ParentNodeName  The name of the desired parent node
 * @param bOutSuccess If the action was a success or not
 * @param OutInfoMsg  More information about the action's result
 * 
 * @return The node that was created
 */
UFUNCTION(BlueprintCallable, Category = "Add Components To Blueprint")
static class USCS_Node* AddNodeToBlueprint(FString BlueprintPath, class USceneComponent* ComponentTemplate, FString ParentNodeName, bool& bOutSuccess, FString& OutInfoMsg);
#include "Engine/SCS_Node.h" // Engine
#include "Kismet2/BlueprintEditorUtils.h" // UnrealEd (Editor Only)

USCS_Node* UExampleClass::AddNodeToBlueprint(FString BlueprintPath, USceneComponent* ComponentTemplate, FString ParentNodeName, bool& bOutSuccess, FString& OutInfoMsg)
{
 // Load blueprint asset
 UBlueprint* Blueprint = Cast<UBlueprint>(StaticLoadObject(UBlueprint::StaticClass(), nullptr, *BlueprintPath));

 if (Blueprint == nullptr)
 {
		bOutSuccess = false;
		OutInfoMsg = FString::Printf(TEXT("Add Node To Blueprint Failed - Path doesn't lead to a valid Blueprint. '%s'"), *BlueprintPath);
		return nullptr;
 }

 // Create new node in blueprint asset
 USCS_Node* NewNode = Blueprint->SimpleConstructionScript->CreateNode(ComponentTemplate->GetClass(), *ComponentTemplate->GetName());

 // Parent node
 USCS_Node* ParentNode = Blueprint->SimpleConstructionScript->FindSCSNode(*ParentNodeName);
 if (ParentNode != nullptr) {
   ParentNode->AddChildNode(NewNode);
 } else {
   TArray<USCS_Node*> AllNodes = Blueprint->SimpleConstructionScript->GetAllNodes();
   // If there are no nodes in the blueprint or if the root node is still the default node
   if (AllNodes.Num() == 0 || AllNodes[0] == Blueprint->SimpleConstructionScript->GetDefaultSceneRootNode()) {
   	// Use this component as root node
   	Blueprint->SimpleConstructionScript->AddNode(NewNode);
   } else {
   	// Use the first node as parent (root node)
   	AllNodes[0]->AddChildNode(NewNode);
   }
 }

 // Copy component's settings onto node
 UEditorEngine::CopyPropertiesForUnrelatedObjects(ComponentTemplate, NewNode->ComponentTemplate);

 // Notify the engine we modified the blueprint components
 FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Blueprint);

 // Return new node
 bOutSuccess = true;
 OutInfoMsg = FString::Printf(TEXT("Add Node To Blueprint Succeeded - '%s'"), *BlueprintPath);
 return NewNode;
}
PrivateDependencyModuleNames.AddRange
(
  new string[] 
  { 
    // Default Modules
    "Core", 
    "CoreUObject", 
    "Engine", 

    // New Modules - Editor Only
    "UnrealEd",
  }
);
  • Add a scene component to a blueprint asset

    /**
     * Editor Only - Will not work in packaged build.
     *
     * Add a scene component to a blueprint asset
     *
     * @param BlueprintPath Path of the blueprint: "/Game/Folder/MyBp"
     * @param bOutSuccess If the action was a success or not
     * @param OutInfoMsg  More information about the action's result
     * 
     * @return The node that was created
     */
    UFUNCTION(BlueprintCallable, Category = "Add Components To Blueprint")
    static class USCS_Node* AddSceneComponentToBlueprint(FString BlueprintPath, bool& bOutSuccess, FString& OutInfoMsg);
    #include "Engine/SCS_Node.h" // Engine
    #include "Kismet2/BlueprintEditorUtils.h" // UnrealEd (Editor Only)
    
    USCS_Node* UExampleClass::AddSceneComponentToBlueprint(FString BlueprintPath, bool& bOutSuccess, FString& OutInfoMsg)
    {
     // Create component
     USceneComponent* Component = NewObject<USceneComponent>(GetTransientPackage(), "My_Scene_Component_Name", RF_Transient);
     Component->SetRelativeLocation(FVector(0.0f, 0.0f, 100.0f));
     Component->SetRelativeRotation(FRotator(0.0f, 0.0f, 0.0f));
     Component->SetRelativeScale3D(FVector(1.0f, 1.0f, 1.0f));
     Component->SetMobility(EComponentMobility::Type::Static);
     Component->SetHiddenInGame(true, false);
     Component->ComponentTags.Add("My Tag");
    
     // Create node in blueprint
     USCS_Node* NewNode = AddNodeToBlueprint(BlueprintPath, Component, "None", bOutSuccess, OutInfoMsg);
     return NewNode;
    }
    PrivateDependencyModuleNames.AddRange
    (
      new string[] 
      { 
        // Default Modules
        "Core", 
        "CoreUObject", 
        "Engine", 
    
        // New Modules - Editor Only
        "UnrealEd",
      }
    );
  • Add a point light component to a blueprint asset

    	/**
     * Editor Only - Will not work in packaged build.
     *
     * Add a point light component to a blueprint asset
     *
     * @param BlueprintPath Path of the blueprint: "/Game/Folder/MyBp"
     * @param bOutSuccess If the action was a success or not
     * @param OutInfoMsg  More information about the action's result
     * 
     * @return The node that was created
     */
    UFUNCTION(BlueprintCallable, Category = "Add Components To Blueprint")
    static class USCS_Node* AddPointLightComponentToBlueprint(FString BlueprintPath, bool& bOutSuccess, FString& OutInfoMsg);
    #include "Engine/SCS_Node.h" // Engine
    #include "Kismet2/BlueprintEditorUtils.h" // UnrealEd (Editor Only)
    #include "Components/PointLightComponent.h" // Engine
    
    USCS_Node* UExampleClass::AddPointLightComponentToBlueprint(FString BlueprintPath, bool& bOutSuccess, FString& OutInfoMsg)
    {
    	// Create component
    	UPointLightComponent* Component = NewObject<UPointLightComponent>(GetTransientPackage(), "My_Point_Light_Component_Name", RF_Transient);
    	Component->SetRelativeLocation(FVector(100.0f, 0.0f, 0.0f));
    	Component->ComponentTags.Add("My Tag");
    	Component->SetLightColor(FLinearColor::Blue);
    	Component->SetIntensity(5000.0f);
    	Component->SetSourceRadius(FMath::RandRange(100.0f, 500.0f));
    	Component->SetAttenuationRadius(FMath::RandRange(1000.0f, 5000.0f));
    
    	// Create node in blueprint
    	USCS_Node* NewNode = AddNodeToBlueprint(BlueprintPath, Component, "My_Scene_Component_Name", bOutSuccess, OutInfoMsg);
    	return NewNode;
    }
    PrivateDependencyModuleNames.AddRange
    (
      new string[] 
      { 
        // Default Modules
        "Core", 
        "CoreUObject", 
        "Engine", 
    
        // New Modules - Editor Only
        "UnrealEd",
      }
    );
  • Add a camera component to a blueprint asset

    /**
     * Editor Only - Will not work in packaged build.
     *
     * Add a camera component to a blueprint asset
     *
     * @param BlueprintPath Path of the blueprint: "/Game/Folder/MyBp"
     * @param bOutSuccess If the action was a success or not
     * @param OutInfoMsg  More information about the action's result
     * 
     * @return The node that was created
     */
    UFUNCTION(BlueprintCallable, Category = "Add Components To Blueprint")
    static class USCS_Node* AddCameraComponentToBlueprint(FString BlueprintPath, bool& bOutSuccess, FString& OutInfoMsg);
    #include "Engine/SCS_Node.h" // Engine
    #include "Kismet2/BlueprintEditorUtils.h" // UnrealEd (Editor Only)
    #include "Camera/CameraComponent.h" // Engine
    
    USCS_Node* UExampleClass::AddCameraComponentToBlueprint(FString BlueprintPath, bool& bOutSuccess, FString& OutInfoMsg)
    {
    	// Create component
    	UCameraComponent* Component = NewObject<UCameraComponent>(GetTransientPackage(), "My_Camera_Component_Name", RF_Transient);
    	Component->SetFieldOfView(66.0f);
    	Component->SetConstraintAspectRatio(true);
    	Component->SetAspectRatio(2.22f);
    	Component->bLockToHmd = false;
    
    	// Create node in blueprint
    	USCS_Node* NewNode = AddNodeToBlueprint(BlueprintPath, Component, "My_Point_Light_Component_Name", bOutSuccess, OutInfoMsg);
    	return NewNode;
    }
    PrivateDependencyModuleNames.AddRange
    (
      new string[] 
      { 
        // Default Modules
        "Core", 
        "CoreUObject", 
        "Engine", 
    
        // New Modules - Editor Only
        "UnrealEd",
      }
    );