ue-game-features
Use this skill when working with Game Feature plugins, modular gameplay, GameFeatureAction, GameFeatureData, GameFrameworkComponentManager, init state system, experience system, modular components, UPawnComponent, UControllerComponent, UGameStateComponent, UPlayerStateComponent, or Lyra-style modular architecture. See references/ for code templates and experience system patterns.
What this skill does
# UE Game Features and Modular Gameplay
You are an expert in Unreal Engine's Game Features plugin system and modular gameplay architecture.
## Context Check
Read `.agents/ue-project-context.md` before proceeding. Determine:
- Whether the `GameFeatures` and `ModularGameplay` plugins are enabled
- Which actors register as component receivers (`AddReceiver`)
- Whether the project uses an init state system or experience-based loading
- Existing `UGameFeatureAction` subclasses or modular component base classes
## Information Gathering
Ask the developer:
1. Are you creating a new Game Feature plugin or extending an existing one?
2. What components or abilities should the feature inject into gameplay actors?
3. Does the feature need async loading or runtime activation/deactivation?
4. Is there an experience/game mode composition system (Lyra-style)?
5. Do components need ordered initialization across features?
---
## Game Feature Plugin Structure
A Game Feature plugin is a standard UE plugin with `Type` set to `"GameFeature"` in its `.uplugin` descriptor. This tells the engine to manage its lifecycle through the Game Features subsystem rather than loading it as a regular plugin.
### .uplugin Descriptor
```cpp
{
"Type": "GameFeature",
"BuiltInInitialFeatureState": "Active", // or "Registered", "Installed"
"Plugins": [
{ "Name": "GameFeatures", "Enabled": true },
{ "Name": "ModularGameplay", "Enabled": true }
]
}
```
`BuiltInInitialFeatureState` controls how far the plugin advances on startup. Use `"Active"` for always-on features, `"Registered"` for features activated by gameplay code, or `"Installed"` for downloadable content loaded on demand.
### UGameFeatureData
Each Game Feature plugin contains a `UGameFeatureData` primary data asset (extends `UPrimaryDataAsset`) that defines what the feature does:
```cpp
// From GameFeatureData.h
UPROPERTY(EditDefaultsOnly, Instanced, Category = "Game Feature | Actions")
TArray<TObjectPtr<UGameFeatureAction>> Actions;
UPROPERTY(EditAnywhere, Category = "Game Feature | Asset Manager")
TArray<FPrimaryAssetTypeInfo> PrimaryAssetTypesToScan;
```
`Actions` is the core — an instanced array of `UGameFeatureAction` subclasses that execute when the feature activates.
### Directory Convention
```
Plugins/GameFeatures/
├── ShooterCore/
│ ├── ShooterCore.uplugin (Type: GameFeature)
│ ├── Content/
│ │ └── ShooterCore.uasset (UGameFeatureData)
│ └── Source/ShooterCoreRuntime/
└── DeathmatchRules/
├── DeathmatchRules.uplugin
└── Content/DeathmatchRules.uasset
```
---
## Plugin State Machine
Game Feature plugins transition through a well-defined state machine. Actions fire at specific transitions and runtime activation must target valid destination states.
### EGameFeaturePluginState Lifecycle
```
Uninitialized → Terminal → UnknownStatus → StatusKnown
→ Installed → Registered → Loaded → Active
```
Each major state has transition states between them (e.g., `Registering`, `Loading`, `Activating`). You target a destination state and the subsystem walks the chain.
### Destination States
| State | Description |
|-------|-------------|
| `Terminal` | Plugin removed from tracking entirely |
| `StatusKnown` | Availability confirmed (exists on disk or bundle) |
| `Installed` | Files on local storage, not yet registered |
| `Registered` | Assets registered with Asset Manager, actions notified |
| `Loaded` | Assets loaded into memory |
| `Active` | Actions fully activated, components injected |
URL protocols: `file:` for built-in disk plugins, `installbundle:` for downloadable features. Convert descriptor path to URL with `UGameFeaturesSubsystem::GetPluginURL_FileProtocol(Path)`.
---
## UGameFeatureAction
`UGameFeatureAction` (`UCLASS(MinimalAPI, DefaultToInstanced, EditInlineNew, Abstract)`) is the base class for all actions. `DefaultToInstanced` + `EditInlineNew` allow instances to be created inline within `UGameFeatureData`'s `Actions` array.
### Lifecycle Methods
```cpp
// Registration phase
virtual void OnGameFeatureRegistering();
virtual void OnGameFeatureUnregistering();
// Loading phase
virtual void OnGameFeatureLoading();
virtual void OnGameFeatureUnloading();
// Activation — primary override point
virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context);
virtual void OnGameFeatureActivating(); // legacy no-arg fallback
// Post-activation confirmation
virtual void OnGameFeatureActivated();
// Deactivation — supports async via context
virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context);
```
`OnGameFeatureActivating(Context)` is the primary override. The base calls the legacy no-arg version for backward compatibility.
### Async Deactivation
When deactivation requires async work, pause it via the context:
```cpp
void UMyAction::OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context)
{
FSimpleDelegate ResumeDelegate = Context.PauseDeactivationUntilComplete(
TEXT("MyAction_AsyncCleanup"));
// Start async work — MUST invoke ResumeDelegate when done or deactivation hangs
AsyncTask(ENamedThreads::GameThread, [ResumeDelegate]()
{
// ... cleanup ...
ResumeDelegate.ExecuteIfBound();
});
}
```
See `references/game-feature-patterns.md` for complete custom action subclass templates.
---
## Built-in Actions
### UGameFeatureAction_AddComponents
`UCLASS(MinimalAPI, meta=(DisplayName="Add Components"), final)`. The most commonly used action — injects components into actors via `UGameFrameworkComponentManager`.
Configuration uses `FGameFeatureComponentEntry`:
```cpp
UPROPERTY(EditAnywhere) TSoftClassPtr<AActor> ActorClass;
UPROPERTY(EditAnywhere) TSoftClassPtr<UActorComponent> ComponentClass;
UPROPERTY(EditAnywhere) uint8 bClientComponent : 1;
UPROPERTY(EditAnywhere) uint8 bServerComponent : 1;
```
Internally stores `TSharedPtr<FComponentRequestHandle>` — RAII removes components when the handle drops (feature deactivates). Set both `bClientComponent` and `bServerComponent` for components needed everywhere, server-only for gameplay logic, client-only for cosmetic.
### Other Built-in Actions
| Action | Purpose |
|--------|---------|
| `UGameFeatureAction_AddCheats` | Register cheat manager extensions |
| `UGameFeatureAction_DataRegistry` | Register data registry sources |
---
## UGameFeaturesSubsystem
`UGameFeaturesSubsystem` (`UEngineSubsystem`) manages all Game Feature plugin lifecycles:
```cpp
UGameFeaturesSubsystem& GFS = UGameFeaturesSubsystem::Get();
```
### Runtime Activation and Deactivation
```cpp
FString PluginURL = UGameFeaturesSubsystem::GetPluginURL_FileProtocol(
TEXT("/MyProject/Plugins/GameFeatures/MyFeature/MyFeature.uplugin"));
// Activate — callback receives const UE::GameFeatures::FResult&
GFS.LoadAndActivateGameFeaturePlugin(PluginURL,
FGameFeaturePluginLoadComplete::CreateUObject(this, &UMyMgr::OnLoaded));
// Deactivate and unload
GFS.DeactivateGameFeaturePlugin(PluginURL);
GFS.UnloadGameFeaturePlugin(PluginURL, /*bKeepRegistered=*/ false);
// Or target a specific state:
GFS.ChangeGameFeatureTargetState(PluginURL, EGameFeatureTargetState::Registered,
FGameFeaturePluginChangeStateComplete());
```
### Query and Observe
```cpp
bool bActive = GFS.IsGameFeaturePluginActive(PluginURL, /*bCheckForActivating=*/ false);
EGameFeaturePluginState State = GFS.GetPluginState(PluginURL);
// Global observer — implement IGameFeatureStateChangeObserver
GFS.AddObserver(MyObserver, UGameFeaturesSubsystem::EObserverPluginStateUpdateMode::CurrentAndFuture);
GFS.RemoveObserver(MyObserver);
```
`IGameFeatureStateChangeObserver` provides: `OnGameFeatureRegistering(Data, PluginName, URL)`, `OnGameFeatureActivating(Data, URL)`, `OnGameFeatureDeactivating(Data, Context, URL)`.
---
## Component Injection System
`UGameFrameworkComponentManager` (`UGameInstanceSubsystem`) is the runtime engine that injects componentRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.