# Ue Actors And Components

> Build and compose gameplay objects from Actors and Components in Unreal C++ — the AActor lifecycle (constructor, PostInitializeComponents, BeginPlay, Tick, EndPlay, Destroyed), the component types (UActorComponent, USceneComponent, UPrimitiveComponent), the root component and attachment, spawning actors and creating/registering components at construction or runtime, and ticking. Use when creating an actor or component, setting up a component hierarchy, attaching components, spawning actors, registering runtime components, or debugging lifecycle/ticking/ attachment/overlap issues.

- Skill: `kevinpbuckley/ue-actors-and-components` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add kevinpbuckley/ue-actors-and-components`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kevinpbuckley/ue-actors-and-components/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: kevinpbuckley (https://skillmd.com/u/kevinpbuckley)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kevinpbuckley/ue-actors-and-components

---


# Actors & components

An **Actor** (`AActor`) is anything you can place or spawn in a level. **Components** are the
reusable pieces of behavior/representation you compose onto actors. "Composition over
inheritance" is the intended design: prefer adding components over deep actor class hierarchies.

## When to use this skill

- Creating a new `AActor` or `UActorComponent` subclass.
- Setting up a component hierarchy (root + attached scene components) and choosing the root.
- Spawning actors (immediate or deferred) or adding/registering components at runtime.
- Wiring overlap/hit events, or deciding what runs in the constructor vs `BeginPlay`.
- Debugging "BeginPlay didn't run", "component has no transform / doesn't render", attachment
  problems, or "my runtime component does nothing".

## Component types

`UActorComponent` is the base for all components. The three tiers, in increasing capability:

| Type | Has transform? | Renders/collides? | Use for |
|---|---|---|---|
| `UActorComponent` | no | no | pure behavior/data (health, inventory, AI logic, abilities) |
| `USceneComponent` | **yes** (location/rotation/scale) | no | transform nodes, attach points, spring arms, cameras |
| `UPrimitiveComponent` | yes | **yes** | meshes, collision, anything drawn or physical |

Concrete primitives you will use most: `UStaticMeshComponent`, `USkeletalMeshComponent`,
`UCapsuleComponent`, `UBoxComponent`, `USphereComponent`, `UCameraComponent`,
`USpringArmComponent`.

Key consequences of the hierarchy:
- Only `USceneComponent`-derived components have a transform, can be **attached** into a hierarchy,
  or be the **root component**.
- Only `USceneComponent`/`UPrimitiveComponent` create a **render state** by default; plain
  `UActorComponent`s don't (nothing to draw).
- Only `UPrimitiveComponent` creates a **physics state** by default (collision/simulation).

See [references/components-and-registration.md](references/components-and-registration.md) for the
full type breakdown, render/physics state, and registration internals.

## AActor lifecycle (order matters)

The canonical order for a typical gameplay actor:

1. **Constructor** — set defaults, `CreateDefaultSubobject` for owned components. No world,
   no gameplay; also runs on the Class Default Object (CDO) and in the editor.
2. `OnConstruction(Transform)` — re-runs whenever a placed actor's properties change (construction
   script). Runs in editor and on spawn; keep it idempotent.
3. `PreInitializeComponents` → per-component `InitializeComponent` → `PostInitializeComponents` —
   components exist & are registered; safe to wire them together.
4. **`BeginPlay`** — gameplay starts. Do gameplay init here (spawning, timers, delegate bindings),
   **not** in the constructor.
5. `Tick(DeltaSeconds)` — per-frame, only if ticking is enabled (see [Ticking](#ticking)).
6. **`EndPlay(Reason)`** — leaving play (destroyed, level change, PIE end, app shutdown);
   clean up timers/delegates here.
7. `Destroyed` (legacy) then `BeginDestroy` / `FinishDestroy` during garbage collection.

There are three distinct **creation paths** that converge before `BeginPlay`: load-from-disk
(`PostLoad`), Play-in-Editor duplication (`PostDuplicate`), and spawning (`PostActorCreated` →
`OnConstruction`). `PostLoad` and `PostActorCreated` are mutually exclusive. The full flow,
including deferred spawn and the GC sequence, is in
[references/actor-lifecycle.md](references/actor-lifecycle.md).

Verified in 5.8 (`GameFramework/Actor.h`): `BeginPlay()`:2125, `EndPlay()`:2132,
`PostInitProperties()`:2343, `Tick(float)`:3060, `PreInitializeComponents()`:3124,
`PostInitializeComponents()`:3127, `OnConstruction()`:3445, `Destroyed()`:3569.

**Constructor vs BeginPlay:** the constructor runs on the CDO and in the editor, with no world.
Never do gameplay logic (spawning, world queries, timers, delegate binding) there — use `BeginPlay`.

## Authoring an actor with components

```cpp
// Pickup.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Pickup.generated.h"

class USphereComponent;
class UStaticMeshComponent;

UCLASS()
class MYGAME_API APickup : public AActor
{
    GENERATED_BODY()
public:
    APickup();

protected:
    virtual void BeginPlay() override;

    // Overlap handlers must be UFUNCTION() with the exact delegate signature, or AddDynamic fails.
    UFUNCTION()
    void OnOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
                   UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,
                   bool bFromSweep, const FHitResult& Sweep);

    UPROPERTY(VisibleAnywhere) TObjectPtr<USphereComponent> Trigger;   // root, collision
    UPROPERTY(VisibleAnywhere) TObjectPtr<UStaticMeshComponent> Mesh;  // visual
};
```

```cpp
// Pickup.cpp
#include "Pickup.h"
#include "Components/SphereComponent.h"
#include "Components/StaticMeshComponent.h"

APickup::APickup()
{
    PrimaryActorTick.bCanEverTick = false;   // default OFF; opt in only if you override Tick

    Trigger = CreateDefaultSubobject<USphereComponent>(TEXT("Trigger"));
    SetRootComponent(Trigger);

    Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
    Mesh->SetupAttachment(Trigger);          // attach in the constructor with SetupAttachment
}

void APickup::BeginPlay()
{
    Super::BeginPlay();
    Trigger->OnComponentBeginOverlap.AddDynamic(this, &APickup::OnOverlap);
}
```

Key rules:
- `CreateDefaultSubobject<T>(TEXT("UniqueName"))` is **constructor-only**; the names must be unique
  within the actor. It is declared on `UObject` (`CoreUObject/Public/UObject/Object.h`).
- Hold component pointers in `UPROPERTY() TObjectPtr<T>` members so the GC keeps them alive and
  they show in the editor. A raw `T*` UPROPERTY also works but `TObjectPtr` is the modern form.
- Set the root with `SetRootComponent` (or assign `RootComponent`). The actor's world transform
  comes from its root.
- In the constructor, attach with `SetupAttachment(Parent)`. At runtime, use `AttachToComponent`.
- Forward-declare component classes in the header and `#include` the concrete component headers in
  the `.cpp` to keep header dependencies light.

## Spawning actors at runtime

```cpp
FActorSpawnParameters Params;
Params.Owner = this;
Params.SpawnCollisionHandlingOverride =
    ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;

APickup* P = GetWorld()->SpawnActor<APickup>(PickupClass, Location, Rotation, Params);

// Deferred spawn: set properties/expose-on-spawn values before BeginPlay runs
AThing* T = GetWorld()->SpawnActorDeferred<AThing>(ThingClass, Transform);
T->Damage = 50.f;
T->FinishSpawning(Transform);   // runs construction → PostInitializeComponents → BeginPlay
```

- `PickupClass` is typically a `UPROPERTY(EditAnywhere) TSubclassOf<APickup>` so designers pick the
  Blueprint subclass. Spawning the C++ class directly skips Blueprint-authored defaults/components.
- Use **deferred spawn** when the actor needs values set *before* `BeginPlay` (e.g. a projectile's
  damage/owner). Plain `SpawnActor` runs the constructor and `BeginPlay` immediately.
- `GetWorld()` can be null on the CDO/in the constructor — only spawn from gameplay code.

Full spawn-parameter fields, collision-handling values, and destroy/pooling guidance:
[references/spawning-and-destroying.md](references/spawning-and-destroying.md).

## Adding components at runtime

```cpp
UStaticMeshComponent* Extra = NewObject<UStaticMeshComponent>(this);
Extra->SetupAttachment(GetRootComponent());  // or AttachToComponent if already registered
Extra->RegisterComponent();                  // REQUIRED so it ticks/renders/collides
```

Runtime components **must** be `RegisterComponent()`-ed — registration is what associates a
component with the world/scene so it can update, render, and collide. Default subobjects created in
the constructor are registered for you during the actor's spawn. Registering many components during
play has a cost; prefer creating them as default subobjects when you can.

## Attachment

```cpp
// Runtime attach/detach (scene components only):
Mesh->AttachToComponent(Target, FAttachmentTransformRules::SnapToTargetIncludingScale, SocketName);
Mesh->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);

// Whole-actor attach (attaches this actor's root to another actor/component):
AttachToActor(OtherActor, FAttachmentTransformRules::KeepRelativeTransform);
```

- `SetupAttachment` is for the constructor / not-yet-registered components; `AttachToComponent`
  attaches immediately and is for play. Using `SetupAttachment` at runtime does nothing without
  registration.
- Attachment rules choose, per channel, whether to keep the world transform or snap to the
  parent/socket. A component can have many children but only one parent; cycles are not allowed.

Attachment rules, sockets, mobility, and relative-vs-world transforms:
[references/attachment-and-transforms.md](references/attachment-and-transforms.md).

## Ticking

- Actors: set `PrimaryActorTick.bCanEverTick = true;` in the constructor, then override `Tick`.
- Components: set `PrimaryComponentTick.bCanEverTick = true;` then override `TickComponent`.
- Both default to **off**. `bCanEverTick` only makes ticking *possible*; you can toggle it at
  runtime with `PrimaryActorTick.SetTickFunctionEnable(true/false)`.
- Prefer events/timers (`ue-timers-and-async`) over ticking when you can — ticking everything is a
  common performance sink. Leave `bCanEverTick = false` for actors that don't need per-frame work.

## Finding components

```cpp
UStaticMeshComponent* M = GetComponentByClass<UStaticMeshComponent>();   // first of class
TArray<USceneComponent*> All;
GetComponents<USceneComponent>(All);                                     // all of class
```

## Gotchas

- **Gameplay logic in the constructor** — runs on the CDO/editor with no world; use `BeginPlay`.
- **Overlap/hit handler not a `UFUNCTION()`** — `AddDynamic` silently fails to fire; the bound
  function must be a `UFUNCTION()` with the *exact* delegate signature.
- **Forgot `RegisterComponent()`** on a runtime component → it won't render/collide/tick.
- **Attaching a non-scene component** — only `USceneComponent`+ can attach or have a transform.
- **`SetupAttachment` at runtime** does nothing without registration; use `AttachToComponent`.
- **No overlaps firing** — the primitive needs collision enabled and `SetGenerateOverlapEvents(true)`
  on both components, with overlapping collision responses.
- **No cleanup in `EndPlay`** — timers/delegates referencing this actor can dangle; clear them.
  `EndPlay` runs for *all* exit reasons, so it's the right place (not `Destroyed`).
- **Static mobility moved at runtime** — only `Movable` components can be transformed during play;
  setting transform on a `Static` component is ignored/asserts.
- **Spawning into a blocked location** can fail and return null; set a collision-handling override.

## Version notes

- `TObjectPtr<T>` is the current idiom for object UPROPERTYs (UE5+); older code uses raw `T*`,
  which still works. See `ue-memory-and-gc`.
- The lifecycle callbacks and component model here are stable across UE5; line numbers in citations
  drift between patch releases, but the header paths and class/function names are stable.

## References & source material

Engine source (UE 5.8, under `Engine/Source/Runtime/`):
- `Engine/Classes/GameFramework/Actor.h` — `AActor` lifecycle, `RootComponent`:1024,
  `PrimaryActorTick`:318, `SetRootComponent`:2493, `AttachToActor`:2029, `FinishSpawning`:3117,
  `GetComponentByClass`:3796.
- `Engine/Classes/Components/ActorComponent.h` — `UActorComponent`, `RegisterComponent`:1322,
  `OnRegister`:830, `InitializeComponent`:919, `BeginPlay`:936, `TickComponent`:976,
  `PrimaryComponentTick`:177, `bWantsInitializeComponent`:340.
- `Engine/Classes/Components/SceneComponent.h` — transforms, `SetupAttachment`:734,
  `AttachToComponent`:752, `DetachFromComponent`:786, `Mobility`:303.
- `Engine/Classes/Components/PrimitiveComponent.h` — rendering/collision, `OnComponentBeginOverlap`:1468,
  `SetGenerateOverlapEvents`:418, `SetCollisionEnabled`:2026.
- `Engine/Classes/Engine/World.h` — `SpawnActor`/`SpawnActorDeferred`:3851, `FActorSpawnParameters`:420.
- `Engine/Classes/Engine/EngineTypes.h` — `FAttachmentTransformRules`:75, `EEndPlayReason`:3670,
  `ESpawnActorCollisionHandlingMethod`:4411.
- `CoreUObject/Public/UObject/Object.h` — `CreateDefaultSubobject`:151.

Official docs (UE 5.8):
- Actor Lifecycle — <https://dev.epicgames.com/documentation/unreal-engine/unreal-engine-actor-lifecycle>
- Components — <https://dev.epicgames.com/documentation/unreal-engine/components-in-unreal-engine>
- Actors — <https://dev.epicgames.com/documentation/unreal-engine/actors-in-unreal-engine>
- Spawning and Destroying an Actor —
  <https://dev.epicgames.com/documentation/unreal-engine/spawning-and-destroying-unreal-engine-actors>
- Actor Ticking — <https://dev.epicgames.com/documentation/unreal-engine/actor-ticking-in-unreal-engine>

Deep-dive references in this skill:
- [references/actor-lifecycle.md](references/actor-lifecycle.md) — full creation paths, component
  init sub-sequence, end-of-life and garbage collection.
- [references/components-and-registration.md](references/components-and-registration.md) — type
  hierarchy, registration/render/physics state, `InitializeComponent` vs `BeginPlay`, ticking.
- [references/attachment-and-transforms.md](references/attachment-and-transforms.md) — attachment
  APIs, transform rules, sockets, mobility.
- [references/spawning-and-destroying.md](references/spawning-and-destroying.md) — spawn variants,
  spawn parameters, deferred spawn, destruction, pooling.

