Unreal Engine MCP
EpicGames/unreal-engine-skills-for-claude-code-plugin
Drives a live Unreal Editor through the unreal-mcp server: spawn actors, edit Blueprints, materials and sequences, change properties and trigger Live Coding.
Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-actor-component-architecture --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ue-actor-component-architecture .claude/skills/ue-actor-component-architecture && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ue-actor-component-architecture" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-actor-component-architecture into .claude/skills/ue-actor-component-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-actor-component-architecture", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-actor-component-architectureType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-actor-component-architecture --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/ue-actor-component-architecture .agents/skills/ue-actor-component-architecture && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ue-actor-component-architecture" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-actor-component-architecture into .agents/skills/ue-actor-component-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-actor-component-architecture", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-actor-component-architecture --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/ue-actor-component-architecture .cursor/skills/ue-actor-component-architecture && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ue-actor-component-architecture" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-actor-component-architecture into .cursor/skills/ue-actor-component-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-actor-component-architecture", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/quodsoler/unreal-engine-skills.git --path skills/ue-actor-component-architecture--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-actor-component-architecture --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/ue-actor-component-architecture .gemini/skills/ue-actor-component-architecture && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ue-actor-component-architecture" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-actor-component-architecture into .gemini/skills/ue-actor-component-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-actor-component-architecture", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install quodsoler/unreal-engine-skills ue-actor-component-architectureInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/ue-actor-component-architecture .github/skills/ue-actor-component-architecture && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ue-actor-component-architecture" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-actor-component-architecture into .github/skills/ue-actor-component-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-actor-component-architecture", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-actor-component-architecture --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/ue-actor-component-architecture .opencode/skills/ue-actor-component-architecture && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ue-actor-component-architecture" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-actor-component-architecture into .opencode/skills/ue-actor-component-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-actor-component-architecture", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ue-actor-component-architectureUnreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.
The skill targets UE 5.8, with APIs checked against its headers and older forms listed as deprecated. It opens by reading `.agents/ue-project-context.md` if present, then routes the request to a section: where code belongs among the constructor, PostInitializeComponents, BeginPlay and EndPlay; creating, attaching and activating components; component hooks such as OnRegister and TickComponent; spawning, including deferred spawn and pooling; tick groups and intervals versus timers; interfaces; and splitting a large actor into components. A mental model reminds the agent never to new or delete actors or components and to use the engine's spawn, destroy and subobject APIs.
Two reference files give the full event order and end-play reasons, and a guide to built-in component types with header paths. A game module's Build.cs needs Core, CoreUObject and Engine. Collision, the gameplay framework and replication are left to sibling skills.
Read from SKILL.md and the folder at commit f3742d7. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Unreal Actor-Component Architecture loads about 7.5k tokens when it runs, and up to ~19k if it reads all its reference files. Until then it costs about 180 tokens; SKILL.md has 1,764 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 1,764 words, ~7,476 tokens.
.claude/skills/ue-actor-component-architecture/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".
Build actors out of components: lifecycle hooks in the right order, spawning (immediate, deferred, pooled), component creation and attachment, ticking, and C++ interfaces. Everything here is in the Engine module (GameFramework/Actor.h, Components/ActorComponent.h, Components/SceneComponent.h, Engine/World.h) on top of CoreUObject; a game module's Build.cs needs "Core", "CoreUObject", "Engine".
Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.
Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.
| Request is about… | Go to |
|---|---|
| Where code belongs: constructor, PostInitializeComponents, BeginPlay, EndPlay | Actor Lifecycle |
| Creating, attaching, activating components | Component System |
| Overriding component hooks (OnRegister, InitializeComponent, TickComponent) | Component Lifecycle Hooks |
| SpawnActor, deferred spawn, pooling | Spawning |
| Tick groups, tick interval, prerequisites, tick vs timer | Ticking |
| Cross-actor capability without casting | Interfaces |
| Splitting a fat actor into components, data-driven loadouts | Composition Patterns |
| Full event order, EEndPlayReason, network and child-actor timing | references/actor-lifecycle.md |
| Which built-in component to use, header paths, member APIs | references/component-types.md |
UObject
└── AActor placeable/spawnable; owns components GameFramework/Actor.h
└── UActorComponent logic only, no transform Components/ActorComponent.h
└── USceneComponent transform + attachment tree Components/SceneComponent.h
└── UPrimitiveComponent rendering + collision + physics Components/PrimitiveComponent.hNever new/delete an actor or component. Actors: UWorld::SpawnActor and AActor::Destroy(bool bNetForce = false, bool bShouldModifyLevel = true) (Actor.h:2327). Components: CreateDefaultSubobject/NewObject and UActorComponent::DestroyComponent(bool bPromoteChildren = false) (ActorComponent.h:1328).
Order from the AActor class comment (Actor.h:243-278); full table with citations in references/actor-lifecycle.md.
AActor::AActor() CDO + every instance. No world. CreateDefaultSubobject, tick config, defaults
UObject::PostLoad() level-placed actors only (not spawned)
UActorComponent::OnComponentCreated() native components on spawn (not when loaded from a level)
AActor::PreRegisterAllComponents() → RegisterComponent() per component → AActor::PostRegisterAllComponents()
AActor::PostActorCreated() spawned actors only, before construction scripts
UserConstructionScript() → AActor::OnConstruction(const FTransform&)
AActor::PreInitializeComponents() gameplay only
UActorComponent::Activate() if bAutoActivate
UActorComponent::InitializeComponent() if bWantsInitializeComponent, once per session
AActor::PostInitializeComponents() components initialized; bind to own components here
AActor::BeginPlay() level is ticking; may be delayed for networked or child actors
AActor::Tick(float DeltaSeconds) if PrimaryActorTick.bCanEverTick
AActor::EndPlay(const EEndPlayReason::Type) base implementation forwards EndPlay to components
AActor::Destroyed() explicit Destroy() only; not on level streaming or game endThe constructor runs on the Class Default Object, where GetWorld() is nullptr. Anything that needs the world or other actors goes in PostInitializeComponents (own components) or BeginPlay (gameplay).
// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
class UStaticMeshComponent;
class UMyHealthComponent;
UCLASS()
class MYGAME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
AMyActor();
protected:
virtual void PostInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION()
void HandleDeath();
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
TObjectPtr<UStaticMeshComponent> MeshComp;
UPROPERTY(VisibleAnywhere, Category="Components")
TObjectPtr<UMyHealthComponent> HealthComp;
};// MyActor.cpp
#include "MyActor.h"
#include "Components/StaticMeshComponent.h"
#include "TimerManager.h"
#include "MyHealthComponent.h"
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = false;
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
SetRootComponent(MeshComp); // SetupAttachment(MeshComp) parents a scene component here; no world needed
HealthComp = CreateDefaultSubobject<UMyHealthComponent>(TEXT("Health")); // logic-only: no attachment
}
void AMyActor::PostInitializeComponents()
{
Super::PostInitializeComponents();
HealthComp->OnDeath.AddDynamic(this, &AMyActor::HandleDeath); // own components are initialized
}
void AMyActor::BeginPlay()
{
Super::BeginPlay();
SetActorTickEnabled(true); // gameplay starts here
}
void AMyActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
GetWorldTimerManager().ClearAllTimersForObject(this);
Super::EndPlay(EndPlayReason); // base forwards EndPlay to components
}
void AMyActor::HandleDeath() { Destroy(); }EEndPlayReason::Type (Engine/EngineTypes.h:3670-3685): Destroyed, LevelTransition, EndPlayInEditor, RemovedFromWorld, Quit. Clear timers and unbind delegates for every reason, then call Super::EndPlay(EndPlayReason).
On clients, BeginPlay "can be delayed for networked or child actors" (Actor.h:275). Property arrival hooks are PreNetReceive()/PostNetReceive() (Actor.h:2943-2946) and PostNetInit(), "always called immediately after spawning and reading in replicated properties" (Actor.h:2958). Replication rules, OnRep_ functions and RPCs are owned by ue-networking-replication.
| Class | Transform | Render/Collision | Use for |
|---|---|---|---|
UActorComponent | No | No | Pure logic and data: health, inventory, cooldowns |
USceneComponent | Yes | No | Anchors, pivots, grouping, attach points |
UPrimitiveComponent | Yes | Yes | Meshes, shapes, anything visible or collidable |
Built-in subclasses, header paths and member APIs: references/component-types.md.
// MyHealthComponent.h
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "MyHealthComponent.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMyOnDeathSignature);
UCLASS(ClassGroup=(MyGame), meta=(BlueprintSpawnableComponent))
class MYGAME_API UMyHealthComponent : public UActorComponent
{
GENERATED_BODY()
public:
UMyHealthComponent();
UPROPERTY(BlueprintAssignable, Category="Health")
FMyOnDeathSignature OnDeath;
UFUNCTION(BlueprintCallable, Category="Health")
void ApplyDamage(float Amount);
protected:
virtual void InitializeComponent() override;
UPROPERTY(EditAnywhere, Category="Health")
float MaxHealth = 100.f;
UPROPERTY(VisibleInstanceOnly, Transient, Category="Health")
float CurrentHealth = 0.f;
};// MyHealthComponent.cpp
#include "MyHealthComponent.h"
UMyHealthComponent::UMyHealthComponent()
{
PrimaryComponentTick.bCanEverTick = false; // event-driven: no per-frame work
bWantsInitializeComponent = true; // opt in to InitializeComponent()
}
void UMyHealthComponent::InitializeComponent()
{
Super::InitializeComponent();
CurrentHealth = MaxHealth; // once per gameplay session, before BeginPlay
}
void UMyHealthComponent::ApplyDamage(float Amount)
{
CurrentHealth = FMath::Max(0.f, CurrentHealth - Amount);
if (CurrentHealth <= 0.f) { OnDeath.Broadcast(); }
}Component replication: bReplicates is private on UActorComponent (ActorComponent.h:267); call SetIsReplicatedByDefault(true) in the constructor or SetIsReplicated(true) later, and the owning actor must replicate. Details in ue-networking-replication.
// In AMyActor (declared: void AddRuntimeLight();)
#include "Components/PointLightComponent.h"
void AMyActor::AddRuntimeLight()
{
// NewObject creates the UObject only; RegisterComponent creates render/physics state and enables tick.
UPointLightComponent* Light = NewObject<UPointLightComponent>(this, TEXT("RuntimeLight"));
Light->SetupAttachment(GetRootComponent()); // allowed before RegisterComponent
Light->RegisterComponent();
AddInstanceComponent(Light); // adds to InstanceComponents: visible in Details, serialized per instance
Light->SetIntensity(5000.f);
}UnregisterComponent() removes world presence but keeps the object (reversible); DestroyComponent() unregisters and marks it for GC. A component whose Outer is an actor is added to that actor's OwnedComponents (ActorComponent.cpp:600 in PostInitProperties, :951 on register), which AActor::AddReferencedObjects reports to GC (Actor.cpp:574), so it stays alive until DestroyComponent() or the actor dies, with or without a UPROPERTY. Still hold your own pointer in a UPROPERTY (TObjectPtr) so it is tracked and nulled safely; a raw pointer dangles after DestroyComponent().
| Call | Where | Header |
|---|---|---|
SetupAttachment(USceneComponent* InParent, FName InSocketName = NAME_None) | Constructor, or any unregistered component | SceneComponent.h:734 |
AttachToComponent(USceneComponent* InParent, const FAttachmentTransformRules& AttachmentRules, FName InSocketName = NAME_None) | Runtime; valid registered or not, but prefer SetupAttachment before registration. Returns bool (false = rejected, parent unchanged) | SceneComponent.h:752 |
DetachFromComponent(const FDetachmentTransformRules& DetachmentRules) | Runtime | SceneComponent.h:786 |
AActor::AttachToComponent(...), AttachToActor(AActor* ParentActor, const FAttachmentTransformRules&, FName SocketName = NAME_None), DetachFromActor(const FDetachmentTransformRules&) | Attach the whole actor via its root; both attach calls return bool | Actor.h:2015, 2029, 2062 |
K2_AttachToComponent(...), K2_AttachToActor(...) | Blueprint nodes only; C++ calls the non-K2_ forms | Actor.h:2006, 2042 |
FAttachmentTransformRules presets (Engine/EngineTypes.h:78-81): KeepRelativeTransform, KeepWorldTransform, SnapToTargetNotIncludingScale, SnapToTargetIncludingScale; per-axis constructor FAttachmentTransformRules(EAttachmentRule InLocationRule, EAttachmentRule InRotationRule, EAttachmentRule InScaleRule, bool bInWeldSimulatedBodies). FDetachmentTransformRules presets (:125-126): KeepRelativeTransform, KeepWorldTransform.
void AMyCharacter::EquipWeapon(UStaticMeshComponent* WeaponMesh)
{
WeaponMesh->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("WeaponSocket"));
}ActorComponent.h)uint8 bAutoActivate:1 is public (:317): set it in the constructor. Runtime: virtual void Activate(bool bReset = false) (:580), virtual void Deactivate() (:586), virtual void SetActive(bool bNewActive, bool bReset = false) (:594), virtual void ToggleActive() (:600), bool IsActive() const (:607; bIsActive is private). Gate activation by overriding virtual bool ShouldActivate() const (:807). Delegates OnComponentActivated / OnComponentDeactivated (:559, :563).
Override these on UActorComponent subclasses; signatures are verbatim from Components/ActorComponent.h.
| Hook | Line | Fires |
|---|---|---|
virtual void OnComponentCreated() | :1331 | Native components when the actor is spawned; not for components loaded from a level |
virtual void OnRegister() / virtual void OnUnregister() | :830, :835 | Around world registration; render/physics state is created after OnRegister |
virtual void InitializeComponent() / virtual void UninitializeComponent() | :919, :955 | Only when bWantsInitializeComponent (:340) is true; once per session |
virtual void BeginPlay() / virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) | :936, :949 | Play start/stop |
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) | :976 | Requires PrimaryComponentTick.bCanEverTick and registration |
virtual void OnComponentDestroyed(bool bDestroyingHierarchy) | :1338 | From DestroyComponent |
HasBeenCreated(), HasBeenInitialized(), HasBegunPlay(), IsRegistered(), IsBeingDestroyed() | :505-520, :1316 | State queries; the bit fields are private |
GetOwner() (:538) and GetOwner<T>() (:542) return the owning actor; GetWorld() is valid once registered.
FActorSpawnParameters (Engine/World.h:420-519): Name, Template, Owner, Instigator, OverrideLevel, SpawnCollisionHandlingOverride, TransformScaleMethod, bNoFail, bDeferConstruction, bAllowDuringConstructionScript, NameMode, ObjectFlags, CustomPreSpawnInitialization. Collision handling values (Engine/EngineTypes.h:4411-4423): Undefined, AlwaysSpawn, AdjustIfPossibleButAlwaysSpawn, AdjustIfPossibleButDontSpawnIfColliding, DontSpawnIfColliding.
// AMyEnemySpawner member: UPROPERTY(EditDefaultsOnly) TSubclassOf<AMyEnemy> EnemyClass;
AMyEnemy* AMyEnemySpawner::SpawnEnemy(const FVector& Location, const FRotator& Rotation)
{
FActorSpawnParameters Params;
Params.Owner = this;
Params.Instigator = GetInstigator();
Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
return GetWorld()->SpawnActor<AMyEnemy>(EnemyClass, Location, Rotation, Params);
}SpawnActorDeferred<T>(UClass* Class, FTransform const& Transform, AActor* Owner = nullptr, APawn* Instigator = nullptr, ESpawnActorCollisionHandlingMethod CollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined, ESpawnActorScaleMethod TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot) (World.h:3851-3870) sets bDeferConstruction = true. Finish with FinishSpawning(const FTransform& Transform, bool bIsDefaultTransform = false, const FComponentInstanceDataCache* InstanceDataCache = nullptr, ESpawnActorScaleMethod TransformScaleMethod = ESpawnActorScaleMethod::OverrideRootScale) (Actor.h:3117). Until then the actor "is in a malformed state" (Actor.h:632).
// AMyEnemy declares: void SetEnemyData(UMyEnemyData* Data);
AMyEnemy* AMyEnemySpawner::SpawnEnemyFromData(const FTransform& SpawnTransform, UMyEnemyData* Data)
{
AMyEnemy* Enemy = GetWorld()->SpawnActorDeferred<AMyEnemy>(EnemyClass, SpawnTransform, this, GetInstigator(),
ESpawnActorCollisionHandlingMethod::AlwaysSpawn);
if (!Enemy) { return nullptr; }
Enemy->SetEnemyData(Data); // runs before OnConstruction and BeginPlay
Enemy->FinishSpawning(SpawnTransform, false, nullptr, ESpawnActorScaleMethod::MultiplyWithRoot);
return Enemy;
}The two defaults differ: SpawnActorDeferred uses MultiplyWithRoot, FinishSpawning uses OverrideRootScale. Pass the scale method explicitly when the root component has a non-unit default scale.
SpawnActor/Destroy churn for projectiles or casings costs GC time. Park actors instead: hide, disable collision and tick; reuse by reversing. AActor has no IsActive(); use IsHidden() (Actor.h:4523) as the parked flag.
Full pooled-actor class (Acquire/Release with GC-safe storage): references/component-types.md.
FTickFunction fields (Engine/EngineBaseTypes.h): bCanEverTick (:213), bStartWithTickEnabled (:217), bTickEvenWhenPaused (:209), bAllowTickOnDedicatedServer (:221), TickGroup (:196), EndTickGroup (:204), TickInterval (:258). Actors use PrimaryActorTick (Actor.h:318), components PrimaryComponentTick (ActorComponent.h:177).
AMyEnemy::AMyEnemy()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = false; // later: SetActorTickEnabled(true)
PrimaryActorTick.TickInterval = 0.1f; // later: SetActorTickInterval(0.1f)
PrimaryActorTick.TickGroup = TG_PostPhysics;
}ETickingGroup (EngineBaseTypes.h:83-109) | Use |
|---|---|
TG_PrePhysics | Default. Input, movement requests, AI decisions |
TG_DuringPhysics | Work that does not read this frame's physics results |
TG_PostPhysics | Camera, IK, anything reading final physics transforms |
TG_PostUpdateWork | Last gameplay group |
TG_StartPhysics, TG_EndPhysics, TG_LastDemotable, TG_NewlySpawned | Engine-internal; never assign |
Ordering between specific objects: AddTickPrerequisiteActor(AActor* PrerequisiteActor) and AddTickPrerequisiteComponent(UActorComponent* PrerequisiteComponent) exist on both AActor (Actor.h:2093, 2097) and UActorComponent (ActorComponent.h:1355, 1359). SetTickableWhenPaused(bool bTickableWhenPaused) (Actor.h:2113, ActorComponent.h:618). Change group at runtime with SetTickGroup(ETickingGroup NewTickGroup) (Actor.h:3566, ActorComponent.h:1351). Fixed-step physics callbacks: bAsyncPhysicsTickEnabled (Actor.h:699) plus virtual void AsyncPhysicsTickActor(float DeltaTime, float SimTime) (Actor.h:2930); see ue-physics-collision.
| Need | Use instead |
|---|---|
| Delayed or repeating work | GetWorldTimerManager().SetTimer(FTimerHandle& InOutHandle, UserClass* InObj, TMethodPtr InTimerMethod, float InRate, bool InbLoop = false, float InFirstDelay = -1.f) (TimerManager.h:167) |
| React to state change | Dynamic multicast delegate on the component, bound in PostInitializeComponents |
| Collision | OnComponentBeginOverlap, OnComponentHit (PrimitiveComponent.h:1457-1475), OnActorBeginOverlap (Actor.h:1368); see ue-physics-collision |
| Cheap per-frame updates | Keep tick but throttle with TickInterval and disable with SetActorTickEnabled(false) when idle |
Use a UINTERFACE for a capability ("can be interacted with") that unrelated actors share; use a component when the behavior owns state or needs to tick. Blueprint-facing exposure rules (BlueprintImplementableEvent, meta= specifiers, latent actions) are owned by ue-blueprint-cpp-interop.
// MyInteractable.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "MyInteractable.generated.h"
UINTERFACE(MinimalAPI, Blueprintable)
class UMyInteractable : public UInterface
{
GENERATED_BODY()
};
class MYGAME_API IMyInteractable
{
GENERATED_BODY()
public:
// C++ default + Blueprint override; UHT also generates Execute_OnInteract(UObject*, AActor*) for safe calls
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="Interaction")
void OnInteract(AActor* InstigatorActor);
};Implementers inherit both classes, class MYGAME_API AMyChest : public AActor, public IMyInteractable, and override virtual void OnInteract_Implementation(AActor* InstigatorActor) override;. Callers never invoke OnInteract directly:
// Caller (AMyCharacter, declared: void TryInteract(AActor* Target);)
void AMyCharacter::TryInteract(AActor* Target)
{
if (Target && Target->Implements<UMyInteractable>()) // U-class for the reflection check
{
IMyInteractable::Execute_OnInteract(Target, this); // works for C++ and Blueprint implementers
}
// Components implementing the interface: FindComponentByInterface<IMyInteractable>() takes the I-class (Actor.h:3852)
}Prefer a flat actor plus components over deep hierarchies (AMyCharacter + UMyHealthComponent + UMyInventoryComponent), with one class and many data assets instead of one subclass per variant. Components talk through the owner (GetOwner()->FindComponentByClass<UMyHealthComponent>()) or through delegates, never through cached raw pointers to siblings. Data-driven loadouts add components at runtime from a TArray<TSubclassOf<UActorComponent>> on a data asset:
void AMyEnemy::ApplyLoadout(const UMyEnemyData* Data)
{
for (const TSubclassOf<UActorComponent>& CompClass : Data->ExtraComponents)
{
UActorComponent* Comp = NewObject<UActorComponent>(this, CompClass);
if (!Comp) { continue; }
Comp->RegisterComponent(); // starts ticking and registers with the world
AddInstanceComponent(Comp); // shows up in the details panel and is saved with the actor
}
}For components injected into actors by plugins or Game Features, use UGameFrameworkComponentManager::AddReceiver(AActor* Receiver, bool bAddOnlyInGameWorlds = true) from ModularGameplay (Beta in 5.8); see ue-game-features.
| Do not emit | Use in 5.8 | Source |
|---|---|---|
FindComponentByInterface<UMyInterface>() | FindComponentByInterface<IMyInterface>() | UE_DEPRECATED(5.5) in GameFramework/Actor.h:3844 |
PreDuplicate(FObjectDuplicationParameters&) | PreDuplicateFromRoot(FObjectDuplicationParameters& DupParams) | UE_DEPRECATED(5.6) in GameFramework/Actor.h:2413 |
Actor->LastRenderTime | GetLastRenderTime() / SetLastRenderTime(float) | UE_DEPRECATED(5.6) in GameFramework/Actor.h:138 |
NetUpdateFrequency = 30.f, MinNetUpdateFrequency = ..., NetCullDistanceSquared = ... | SetNetUpdateFrequency(), SetMinNetUpdateFrequency(), SetNetCullDistanceSquared() | UE_DEPRECATED(5.5) in GameFramework/Actor.h:898-909 |
BeginReplication() / EndReplication() overrides | OnReplicationStartedForIris / OnStopReplicationForIris / FillReplicationParams; see ue-networking-replication | UE_DEPRECATED(5.7) in GameFramework/Actor.h:3493-3506 |
APawn::GetMovementBase() | GetMovementBaseObject() / GetMovementBaseInterfaceData(); see ue-character-movement | UE_DEPRECATED(5.8) in GameFramework/Pawn.h:59 |
AttachTo(...), K2_AttachTo(...), AttachRootComponentTo(...) | AttachToComponent(Parent, FAttachmentTransformRules, SocketName) | UE_DEPRECATED(4.17) in GameFramework/Actor.h:1991, Components/SceneComponent.h:740 |
AttachRootComponentToActor(...) | AttachToActor(ParentActor, FAttachmentTransformRules, SocketName) | UE_DEPRECATED(4.17) in GameFramework/Actor.h:2018 |
DetachFromParent(bool), DetachRootComponentFromParent(bool) | DetachFromComponent(FDetachmentTransformRules), DetachFromActor(FDetachmentTransformRules) | UE_DEPRECATED(4.12) in Components/SceneComponent.h:768; UE_DEPRECATED(4.17) in GameFramework/Actor.h:2045 |
Comp->bReplicates = true | SetIsReplicatedByDefault(true) (constructor) or SetIsReplicated(true) | private member, Components/ActorComponent.h:264-267 |
Comp->bCreatedByConstructionScript | Comp->CreationMethod == EComponentCreationMethod::UserConstructionScript or IsCreatedByConstructionScript() | @deprecated Replaced by CreationMethod, Components/ActorComponent.h:306-310 |
SceneComp->RelativeLocation = ..., SceneComp->bVisible = ..., SceneComp->AttachParent | SetRelativeLocation(), SetVisibility(), GetAttachParent() | private members, Components/SceneComponent.h:109-183 |
Actor->bHidden | IsHidden() / SetActorHiddenInGame(bool) | private member, GameFramework/Actor.h:365 |
GetComponentsByClass(...) in C++ (the C++ name is K2_GetComponentsByClass) | GetComponents<T>(OutArray) or TInlineComponentArray<T*> | "intended to only be used by blueprints", GameFramework/Actor.h:3801-3807 |
LightmapType on primitives | GetLightmapType() / SetLightmapType() | UE_DEPRECATED(5.5) in Components/PrimitiveComponent.h:359 |
World access in the constructor: GetWorld() is nullptr on the CDO; SpawnActor, timers and lookups belong in BeginPlay, component binding in PostInitializeComponents.
Skipping Super::: every lifecycle override calls its Super:: (BeginPlay first thing; EndPlay(EndPlayReason) last). AActor::EndPlay is what forwards EndPlay to components; RouteEndPlay ensures against a missing Super::EndPlay (Actor.cpp:3230).
Pooled or cached actors outside a UPROPERTY: a plain TArray<AMyProjectile*> member is invisible to GC; declare UPROPERTY() TArray<TObjectPtr<AMyProjectile>>. For non-owning references in non-UObject code use TWeakObjectPtr<AActor> and check IsValid().
AttachToComponent in the constructor: the header allows it on unregistered components, but SetupAttachment is the intended call there (SceneComponent.h:745-746); use AttachToComponent from BeginPlay onward and check its bool result.
NewObject without RegisterComponent: the component never gets render or physics state and never ticks. Also call AddInstanceComponent if it should appear in the Details panel and survive serialization.
Deferred spawn without FinishSpawning: the actor stays in a malformed state (Actor.h:632); always pair SpawnActorDeferred with FinishSpawning.
Calling an interface method directly: Target->OnInteract(...) bypasses Blueprint implementers. Test with Implements<UMyInteractable>(), call through IMyInteractable::Execute_OnInteract(Target, ...).
Polling in Tick: if (HealthComp->IsDead()) every frame is replaced by binding OnDeath once; disable tick with SetActorTickEnabled(false) when nothing needs per-frame work.
Assuming child actors exist in PostInitializeComponents: UChildActorComponent children may begin play late (Actor.h:275); read GetChildActor() in or after BeginPlay.
Writing private component flags: bReplicates, bIsActive, bHasBegunPlay, RelativeLocation and bVisible are private; use the setters and queries listed in the tables above.
ue-cpp-foundations — UCLASS/UPROPERTY/UFUNCTION specifiers, TObjectPtr vs TWeakObjectPtr, subsystems, GC rulesue-gameplay-framework — GameMode, GameState, PlayerController, Pawn, Character, damage without GASue-physics-collision — collision channels and profiles, overlap and hit events, sweeps, async physics tickue-networking-replication — SetReplicates, property replication, OnRep, RPCs, subobject replication, Irisue-gameplay-cameras — USpringArmComponent, UCameraComponent, PlayerCameraManager, Gameplay Cameras pluginue-blueprint-cpp-interop — Blueprint-implementable interfaces, BlueprintNativeEvent rules, latent actions, meta specifiersue-character-movement — CharacterMovementComponent, movement base API, CMC vs Moverue-animation-system — USkeletalMeshComponent animation, AnimInstance, montagesue-audio-system — UAudioComponent playback, attenuation, MetaSoundsue-niagara-effects — UNiagaraComponent, system spawning, user parametersue-game-features — ModularGameplay components, UGameFrameworkComponentManager, Game Feature actionsue-gameplay-abilities — UAbilitySystemComponent placement on actorsue-state-trees — UStateTreeComponent on actors and AI controllersue-ai-navigation — perception and navigation componentsue-procedural-generation — UProceduralMeshComponent, UDynamicMeshComponent, instancing at scaleue-editor-tools — detail customizations, editor utility widgets, UToolMenus and editor subsystemsue-input-system — Enhanced Input actions, mapping contexts, triggers, modifiers and user settingsue-mass-entity — Mass processors, fragments, queries and entity traitsue-materials-rendering — material instances, parameter collections, render targets and post processue-sequencer-cinematics — Level Sequences, playback, cine cameras and Movie Render Graphue-world-level-streaming — World Partition, level streaming, data layers and travel© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files (references) in skills/ue-actor-component-architecture of quodsoler/unreal-engine-skills.
Open the folder on GitHubat commit f3742d7
Unreal Actor-Component Architecture next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Unreal Actor-Component Architecture this skillquodsoler/unreal-engine-skills | 362 | — | ~7.5k | Automated safety check: Pass | MIT | |
| Unreal Engine MCPEpicGames/unreal-engine-skills-for-claude-code-plugin | 338 | — | ~1.8k | Automated safety check: Pass | MIT | |
| Unreal Live CodingItalink/UnrealClientProtocol | 127 | — | ~1k | Automated safety check: Pass | MIT | |
| Unreal Cpp Gameplayukanwat/overtime | 387 | 1 repos | ~1.5k | Automated safety check: Pass | Apache-2.0 | |
| Unreal Enhanced Inputukanwat/overtime | 387 | 1 repos | ~1.5k | Automated safety check: Pass | Apache-2.0 | |
| Unreal Niagaraukanwat/overtime | 387 | 1 repos | ~1.5k | Automated safety check: Pass | Apache-2.0 |
EpicGames/unreal-engine-skills-for-claude-code-plugin
Drives a live Unreal Editor through the unreal-mcp server: spawn actors, edit Blueprints, materials and sequences, change properties and trigger Live Coding.
Italink/UnrealClientProtocol
Trigger Live Coding compilation via UCP. An agent skill from Italink/UnrealClientProtocol.
ukanwat/overtime
Write Unreal Engine 5 C++ gameplay code: the UCLASS/UPROPERTY/UFUNCTION reflection macros, the Gameplay Framework (GameMode, Pawn, Character, PlayerController, Actor components), and the module…
ukanwat/overtime
Set up player input in Unreal Engine 5 with Enhanced Input: Input Actions, Input Mapping Contexts, modifiers and triggers, adding the mapping context, and binding actions by ETriggerEvent.
ukanwat/overtime
Create and control VFX in Unreal Engine 5 with Niagara: systems and emitters, modules and the spawn/update stages, exposed User parameters, and spawning or driving effects from Blueprints or C++.
JetBrains/skills
A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…
quodsoler/unreal-engine-skills
Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.
quodsoler/unreal-engine-skills
Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.
quodsoler/unreal-engine-skills
Picks and applies the right Unreal Engine C++ concurrency API, from UE::Tasks and FPipe to ParallelFor, FRunnable, locks and timers, with game-thread safety rules.
quodsoler/unreal-engine-skills
A skill your agent uses when playing, mixing or debugging sound in Unreal Engine — one-shot SFX, looping ambience, music, dialogue or procedural audio.
quodsoler/unreal-engine-skills
Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.
quodsoler/unreal-engine-skills
Reference for writing and debugging UCharacterMovementComponent code in Unreal Engine C++: custom movement modes, floor detection, root motion, prediction and gravity.
Works with
Categories
Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition. 8, with APIs checked against its headers and older forms listed as deprecated.md` if present, then routes the request to a section: where code belongs among the constructor, PostInitializeComponents, BeginPlay and EndPlay; creating, attaching and activating components; component hooks such as OnRegister and TickComponent; spawning, including deferred spawn and pooling; tick groups and intervals versus timers; interfaces; and splitting a large actor into components.
Unreal Actor-Component Architecture fits situations like: deciding what belongs in an actor's constructor versus BeginPlay; spawning actors with SpawnActorDeferred and setting them up before FinishSpawning; attaching components and fixing root component or transform rules; replacing a heavy actor with small components or building an actor pool.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a claude-code`. Or copy the skill folder (skills/ue-actor-component-architecture in quodsoler/unreal-engine-skills) into .claude/skills/ue-actor-component-architecture in your project. Claude Code loads it when a task matches its description.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a codex`. Or copy the skill folder (skills/ue-actor-component-architecture in quodsoler/unreal-engine-skills) into .agents/skills/ue-actor-component-architecture in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add quodsoler/unreal-engine-skills --skill ue-actor-component-architecture -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ue-actor-component-architecture, .gemini/skills/ue-actor-component-architecture, .github/skills/ue-actor-component-architecture and .opencode/skills/ue-actor-component-architecture in your project.
SKILL.md names no scripts, command-line tools or credentials: Unreal Actor-Component Architecture is instructions for the agent only. Our summary lists: An Unreal Engine C++ project, with the game module depending on Core, CoreUObject and Engine.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Unreal Actor-Component Architecture is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.5k tokens (SKILL.md is roughly 30k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 12k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Unreal Actor-Component Architecture: Unreal Engine MCP (EpicGames/unreal-engine-skills-for-claude-code-plugin, 338 stars), Unreal Live Coding (Italink/UnrealClientProtocol, 127 stars), Unreal Cpp Gameplay (ukanwat/overtime, 387 stars) and Unreal Enhanced Input (ukanwat/overtime, 387 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
quodsoler (a GitHub user) maintains it in quodsoler/unreal-engine-skills, which has 362 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on September 28, 2026.
Source: quodsoler/unreal-engine-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.