-
Notifications
You must be signed in to change notification settings - Fork 67
Actors and components
This covers the basics of using AActor and UActorComponent
The properties AActor.PrimaryActorTick
/ UActorComponent.PrimaryComponentTick
are used to control the ticking functionality of actors and components. These properties are of type FTickFunction
which is a struct (essentially a pointer to the C++ FTickFunction
).
Enabling AActor tick:
[UClass]
class ATickTest1 : AActor
{
public override void Initialize(FObjectInitializer initializer)
{
base.Initialize(initializer);
PrimaryActorTick.SetStartWithTickEnabled(true);
PrimaryActorTick.SetCanEverTick(true);
}
protected override void ReceiveTick_Implementation(float DeltaSeconds)
{
base.ReceiveTick_Implementation(DeltaSeconds);
}
}
Enabling UActorComponent tick:
[UClass]
class UTickTest2 : UActorComponent
{
public override void Initialize(FObjectInitializer initializer)
{
base.Initialize(initializer);
PrimaryComponentTick.SetStartWithTickEnabled(true);
PrimaryComponentTick.SetCanEverTick(true);
}
protected override void ReceiveTick_Implementation(float DeltaSeconds)
{
base.ReceiveTick_Implementation(DeltaSeconds);
}
}
It's best to enable tick in the Initialize
function as the ticker is registered with the engine tickers just before the C# BeginPlay
function is called. If you need to enable the ticker in BeginPlay
you may need to manually register the ticker via FTickFunction.RegisterTickFunction
.
This is an example of adding a UStaticMeshComponent
as the RootComponent
and then attaching a UTextRendererComponent
.
[UClass]
class ATestActor : AActor
{
[UProperty, EditAnywhere, BlueprintReadWrite]
public UStaticMeshComponent Mesh { get; set; }
[UProperty, EditAnywhere, BlueprintReadWrite]
public UTextRenderComponent TextRenderer { get; set; }
public override void Initialize(FObjectInitializer initializer)
{
UStaticMesh cubeMesh = ConstructorHelpers.FObjectFinder<UStaticMesh>.Find("StaticMesh'/Engine/BasicShapes/Cube.Cube'");
if (cubeMesh != null)
{
Mesh = initializer.CreateDefaultSubobject<UStaticMeshComponent>(this, (FName)"Mesh");
Mesh.SetStaticMesh(cubeMesh);
RootComponent = Mesh;
TextRenderer = initializer.CreateDefaultSubobject<UTextRenderComponent>(this, (FName)"TextRenderer");
TextRenderer.SetupAttachment(Mesh);
using (FText text = FText.FromString("Text component test"))
{
TextRenderer.SetText(text);
}
}
}
}
This is an example of spawning an AActor and adding a UStaticMeshComponent
at runtime in the BeginPlay
function of a AGameMode
defined type.
[UClass]
class ATestGameMode : AGameMode
{
protected override void BeginPlay()
{
base.BeginPlay();
UStaticMesh cubeMesh = ConstructorHelpers.FObjectFinder<UStaticMesh>.Find("StaticMesh'/Engine/BasicShapes/Cube.Cube'");
if (cubeMesh != null)
{
AActor actor = World.SpawnActor<AActor>(default(FVector), default(FRotator));
UStaticMeshComponent meshComponent = NewObject<UStaticMeshComponent>(actor, (FName)"Mesh");
meshComponent.SetStaticMesh(cubeMesh);
meshComponent.RegisterComponent();
actor.RootComponent = meshComponent;
}
}
}
By default components wont show up in the "Add Component" list in the editor. To enable this add the [BlueprintSpawnableComponent]
attribute.
[UClass, BlueprintSpawnableComponent]
class UTestComponent : UActorComponent
{
}
This finds all actors of type ASomeActor
in the world, then finds all mesh components on those actors and disables the renderer.
[UClass]
class AFindActorsTest : AActor
{
protected override void BeginPlay()
{
base.BeginPlay();
ASomeActor[] actors = UGameplayStatics.GetAllActorsOfClass<ASomeActor>(this);
foreach (ASomeActor actor in actors)
{
UStaticMeshComponent[] components = actor.GetComponentsByClass<UStaticMeshComponent>();
foreach (UStaticMeshComponent component in components)
{
component.SetHiddenInGame(true);
}
}
}
}
The most common way of handling input is the SetupPlayerInputComponent
function of a ACharacter
derived class.
[UClass]
class AInputTestCharacter : ACharacter
{
protected override void SetupPlayerInputComponent(UInputComponent playerInputComponent)
{
base.SetupPlayerInputComponent(playerInputComponent);
// Set-up "Trigger" in the input bindings in the editor.
playerInputComponent.BindAction("Trigger", EInputEventType.Pressed, OnTrigger);
}
// Must be marked as a [UFunction] so that the engine can call this function when the button is pressed
[UFunction]
private void OnTrigger()
{
PrintString("OnTrigger", FLinearColor.Red);
}
}
It's also possible to handle input on any AActor
instance by enabling input for that actor and then binding the inputs. The following shows an example of explicitly binding the 'C' keyboard key, and allowing that input event to also be handled elsewhere by disabling ConsumeInput
.
[UClass]
class AInputTestActor : AActor
{
protected override void BeginPlay()
{
base.BeginPlay();
APlayerController playerController = World.GetFirstPlayerController();
if (playerController != null)
{
EnableInput(playerController);// This will create InputComponent (if not already created)
FInputKeyBindingHandle handle = InputComponent.BindKey(EKeys.C, EInputEventType.Pressed, CPressed);
handle.ConsumeInput = false;
}
}
[UFunction]
void CPressed()
{
World.PrintString(GetFullName(), FLinearColor.Red);
}
}