Skip to main content

Blueprint Mixin

Mixin allows developers to combine TypeScript and U.E Classes seamlessly.

Example use cases include:

  • Overriding existing blueprint and C++ methods within TypeScript
  • Extending classes with new TypeScript methods and fields

Table Of Contents

Usage

Mixin With C++ Class

C++
// ExampleMixinActor.h
#pragma once

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

UCLASS()
class AExampleMixinActor : public AActor
{
GENERATED_BODY()

public:
UFUNCTION(BlueprintNativeEvent)
void ExampleFunction();
void ExampleFunction_Implementation()
{
UE_LOG(LogTemp, Warning, TEXT("AExampleMixinActor::ExampleFunction() Executed"));
}
};
TypeScript
// MixinExample.ts
import * as UE from 'ue'
import * as Puerts from 'puerts'

const GameInstance = Puerts.argv.getByName("GameInstance") as UE.GameInstance;
const World = GameInstance?.GetWorld();

interface ExtendedMixinActor extends UE.ExampleMixinActor {};
class ExtendedMixinActor implements ExtendedMixinActor {
ExampleFunction(): void
{
console.warn("ExtendedMixinActor::ExampleFunction() Executed");
}
}

// Generate The Mixin Class
const GeneratedClass = Puerts.blueprint.mixin(UE.ExampleMixinActor, ExtendedMixinActor, {
inherit: true // 'true' generated a new class object instead of applying mixin globally
}).StaticClass();

// Spawn the actor from mixin class
const SpawnedActor = UE.GameplayStatics.BeginDeferredActorSpawnFromClass(World, GeneratedClass, UE.Transform.Identity) as ExtendedMixinActor;
UE.GameplayStatics.FinishSpawningActor(SpawnedActor, UE.Transform.Identity);

SpawnedActor?.ExampleFunction();

Mixin With Blueprint Class

TypeScript
// MixinExample.ts
import * as UE from 'ue'
import * as Puerts from 'puerts'

const GameInstance = Puerts.argv.getByName("GameInstance") as UE.GameInstance;
const World = GameInstance?.GetWorld();

interface ExtendedMixinBlueprint extends UE.Game.ExampleMixinBlueprint.ExampleMixinBlueprint_C {};
class ExtendedMixinBlueprint implements ExtendedMixinBlueprint {
ExampleBlueprintFunction(): void {
console.warn("ExtendedMixinBlueprint::ExampleBlueprintFunction() Executed");
}
}

// Load In The Class To Extend
let BlueprintClass = UE.Class.Load('/Game/ExampleMixinBlueprint.ExampleMixinBlueprint_C');
const InterperatedBlueprintClass = Puerts.blueprint.tojs(BlueprintClass);

// Generate The Mixin Class
const GeneratedClass = Puerts.blueprint.mixin(InterperatedBlueprintClass, ExtendedMixinBlueprint, {
inherit: true // 'true' generated a new class object instead of applying mixin globally
}).StaticClass();

// Spawn the actor from mixin class
const SpawnedActor = UE.GameplayStatics.BeginDeferredActorSpawnFromClass(World, GeneratedClass, UE.Transform.Identity) as ExtendedMixinBlueprint;
UE.GameplayStatics.FinishSpawningActor(SpawnedActor, UE.Transform.Identity);

SpawnedActor?.ExampleBlueprintFunction();

API Reference

Mixin Config

You can pass an optional configuration object:

TypeScript
type MixinConfig = { objectTakeByNative?: boolean, inherit?: boolean, generatedClass?: Class };
// MixinExample.ts
const GeneratedClass = Puerts.blueprint.mixin(A, B, {
objectTakeByNative: true, // `true` = UE object owns the garbage collection
inherit: true // 'true' generated a new class object instead of applying mixin globally
}).StaticClass();
Parameter NameDescription
objectTakeByNativeShould the lifetime of the mixin functions return object be handled by UE or JavaScript garbage collection. (True for UE)
inheritShould the mixin function generate a new class object or apply globally. (True for new class object)
generatedClassAn output variable used to gather the generated class object. (Deprecated due to .StaticClass())

Using the super keyword

If you wish to use the super keyword in your mixin overrides, an intermediary class is required.

TypeScript
// MixinExample.ts
import * as UE from 'ue'
import * as Puerts from 'puerts'

const GameInstance = Puerts.argv.getByName("GameInstance") as UE.GameInstance;
const World = GameInstance?.GetWorld();

// Define intermediary class
interface ExampleMixinActor extends UE.ExampleMixinActor {};
class ExampleMixinActor implements ExampleMixinActor {}
Object.setPrototypeOf(ExampleMixinActor.prototype, UE.ExampleMixinActor.prototype);

// Define Mixin Override Class
class ExtendedMixinActor extends ExampleMixinActor {
ExampleFunction(): void
{
console.warn("ExtendedMixinActor: Attempting to call Super.ExampleFunction()");
super.ExampleFunction();
}
}

// Generate The Mixin Class
const GeneratedClass = Puerts.blueprint.mixin(UE.ExampleMixinActor, ExtendedMixinActor, {
inherit: true // 'true' generated a new class object instead of applying mixin globally
}).StaticClass();

// Spawn the actor from mixin class
const SpawnedActor = UE.GameplayStatics.BeginDeferredActorSpawnFromClass(World, GeneratedClass, UE.Transform.Identity) as ExtendedMixinActor;
UE.GameplayStatics.FinishSpawningActor(SpawnedActor, UE.Transform.Identity);

SpawnedActor?.ExampleFunction();

Notes

Limited function override support

All functions and events defined in blueprint are supported. C++ functions must be tagged as BlueprintNativeEvent or BlueprintImplementableEvent.