Actors and Components
Actors and components are two of the fundamental gameplay types in unreal code.
Creating a new actor or component type in script is as simple as creating a new script file and adding a class that inherits from an actor type:
class AMyActor : AActor{}
class UMyComponent : UActorComponent{}Note: The script plugin automatically sets the most useful class flags for any script classes, adding a
UCLASS()specifier is not necessary in script, but can still optionally be used to configure additional class settings.
Default Components
Unlike in C++, script classes do not make use of their constructors for creating components.
To add a default component to the actor, use the DefaultComponent specifier for them.
Default components are automatically created on the actor when it is spawned.
The following class will have two components on it when placed. A scene component at the root, and the custom UMyComponent we declared before:
class AExampleActor : AActor{ UPROPERTY(DefaultComponent) USceneComponent SceneRoot;
UPROPERTY(DefaultComponent) UMyComponent MyComponent;}Component Attachments
Likewise, the default attachment hierarchy is specified in UPROPERTY specifiers, rather than set up in a constructor. Use the Attach = and AttachSocket = specifiers.
If an explicit attachment is not specified, the component will be attached to the actor’s root.
class AExampleActor : AActor{ // Explicit root component UPROPERTY(DefaultComponent, RootComponent) USceneComponent SceneRoot;
// Will be attached to SceneRoot by default, as no attachment is specified UPROPERTY(DefaultComponent) USkeletalMeshComponent CharacterMesh;
// Will be attached to the CharacterMesh' RightHand socket UPROPERTY(DefaultComponent, Attach = CharacterMesh, AttachSocket = RightHand) UStaticMeshComponent WeaponMesh;
// Will be attached to the WeaponMesh UPROPERTY(DefaultComponent, Attach = WeaponMesh) UStaticMeshComponent ScopeMesh;}Note: You can explicitly note which component should be the default root component with the
RootComponentspecifier. If you do not add this specifier, the first component to be created will become the root.
Default Statements
To assign default values to properties on the actor’s components, you can use default statements:
class AExampleActor : AActor{ UPROPERTY(DefaultComponent, RootComponent) USceneComponent SceneRoot;
UPROPERTY(DefaultComponent) USkeletalMeshComponent CharacterMesh;
// The character mesh is always placed a bit above the actor root default CharacterMesh.RelativeLocation = FVector(0.0, 0.0, 50.0);
UPROPERTY(DefaultComponent) UStaticMeshComponent ShieldMesh;
// The shield mesh is hidden by default, and should only appear when taking damage default ShieldMesh.bHiddenInGame = true; // The shield mesh should not have any collision default ShieldMesh.SetCollisionEnabled(ECollisionEnabled::NoCollision);}Working with Components
Retrieving Components
If you have an actor and want to find a component of a type on it, use UMyComponentClass::Get():
AActor Actor;
// Retrieve the first skeletal mesh component we can find on the actorUSkeletalMeshComponent SkelComp = USkeletalMeshComponent::Get(Actor);
// Find the specific skeletal mesh component with this component nameUSkeletalMeshComponent WeaponComp = USkeletalMeshComponent::Get(Actor, n"WeaponMesh");If no component of the specified type exists, this will return nullptr.
Use UMyComponentClass::GetOrCreate() to retrieve a potential existing component, or create it if one does not exist already:
// Find our own interaction handling component on the actor.// If it does not exist, create it.UInteractionComponent InteractComp = UInteractionComponent::GetOrCreate(Actor);
// Find an interaction handling component specifically named "ClimbingInteraction",// or create a new one with that nameauto ClimbComp = UInteractionComponent::GetOrCreate(Actor, n"ClimbingInteraction");Adding New Components
Creating a new component works similarly by calling UMyComponentClass::Create().
Specifying a component name is optional, if none is specified one will be automatically generated.
ACharacter Character;
// Create a new static mesh component on the character and attach it to the character meshUStaticMeshComponent NewComponent = UStaticMeshComponent::Create(Character);NewComponent.AttachToComponent(Character.Mesh);Tip: If you have a dynamic
TSubclassOf<>orUClassfor a component class, you can also use the generic functions on actors for these operations by usingActor.GetComponent(),Actor.GetOrCreateComponent(), orActor.CreateComponent()
Spawning Actors
Helpers for spawning actors of a specific type are also available:
// Spawn a new Example Actor at the specified location and rotationFVector SpawnLocation;FRotator SpawnRotation;AExampleActor SpawnedActor = AExampleActor::Spawn(SpawnLocation, SpawnRotation);Spawning a Blueprinted Actor
It is often needed to dynamically spawn an actor blueprint, rather than a script actor baseclass.
To do this, use a TSubclassOf<> property to reference the blueprint, and use the global SpawnActor() function.
An example of a spawner actor that can be configured to spawn any blueprint of an example actor:
class AExampleSpawner : AActor{ /** * Which blueprint example actor class to spawn. * This needs to be configured either in the level, * or on a blueprint child class of the spawner. */ UPROPERTY() TSubclassOf<AExampleActor> ActorClass;
UFUNCTION(BlueprintOverride) void BeginPlay() { FVector SpawnLocation; FRotator SpawnRotation;
AExampleActor SpawnedActor = Cast<AExampleActor>( SpawnActor(ActorClass, SpawnLocation, SpawnRotation) ); }}Construction Script
Actor construction script can be added by overriding the ConstructionScript() blueprint event.
From construction scripts, you can create new components and override properties like normal.
For example, an actor that creates a variable amount of meshes inside it based on its settings in the level could look like this:
class AExampleActor : AActor{ // How many meshes to place on the actor UPROPERTY() int SpawnMeshCount = 5;
// Which static mesh to place UPROPERTY() UStaticMesh MeshAsset;
UFUNCTION(BlueprintOverride) void ConstructionScript() { Print(f"Spawning {SpawnMeshCount} meshes from construction script!");
for (int i = 0; i < SpawnMeshCount; ++i) { // Construct a new static mesh on this actor UStaticMeshComponent MeshComp = UStaticMeshComponent::Create(this); // Set the mesh we wanted for it MeshComp.SetStaticMesh(MeshAsset); } }}Getting All Actors or Components
To get all components of a particular type that are on an actor, use Actor.GetComponentsByClass() and pass in the array.
This function takes a ? parameter, and will determine which component type to look for by the type of array you pass in.
For example, to get all static meshes on an actor:
AActor Actor;
TArray<UStaticMeshComponent> StaticMeshComponents;Actor.GetComponentsByClass(StaticMeshComponents);
for (UStaticMeshComponent MeshComp : StaticMeshComponents){ Print(f"Static Mesh Component: {MeshComp.Name}");}Similarly, to get all actors of a particular type that are currently in the world, use the GetAllActorsOfClass() global function, and pass in an array of the type of actor you want:
// Find all niagara actors currently in the levelTArray < ANiagaraActor > NiagaraActors;GetAllActorsOfClass(NiagaraActors);Note: Getting all actors of a class requires iterating all actors in the level, and should not be used from performance-sensitive contexts. That is, try running it once and storing the value rather than using it every tick.
Override Components
Unreal provides a mechanism for overriding one of a parent actor class’ default components to use a child component class instead of the one specified on the parent actor.
In script, this can be accessed by using the OverrideComponent specifier:
class ABaseActor : AActor{ // This base actor specifies a root component that is just a scene component UPROPERTY(DefaultComponent, RootComponent) USceneComponent SceneRoot;}
class AChildActor : ABaseActor{ /** * Because static meshes are a type of scene component, * we can use an override component to turn the base class' root * scene component into a static mesh. */ UPROPERTY(OverrideComponent = SceneRoot) UStaticMeshComponent RootStaticMesh;}Note: Override components are similar to using
ObjectInitializer.SetDefaultSubobjectClass()in a C++ constructor.