ue-cpp-foundations について
Unreal Engine 5.8 の基礎的な C++ API を扱うスキルガイドです。モジュール開発者向けに、リフレクション、コンテナ、デリゲート、オブジェクトのライフタイム、サブシステムの API とコード例をまとめています。
主な機能
- 01リフレクションマクロとプロパティ
- 02コンテナとデリゲートのパターン
- 03文字列とオブジェクトのライフタイム
- 04CDO と非 null パラメーター
- 05エンジンサブシステムのパターン
活用シーン
- 01UCLASS と UPROPERTY の宣言
- 02UObject ポインターと GC 管理の選択
- 03C++ デリゲートとイベントの実装
- 04ゲームまたはエディターサブシステムへのアクセス
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ quodsoler/ unreal-engine-skills --skill ue-cpp-foundationsインストール後、Claude Code で/ue-cpp-foundationsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/container-patterns.mddelegate-patterns.mdproperty-specifiers.md詳細
UE C++ の基礎
対象エンジン:UE 5.8。以下の API は 5.8 のヘッダーで検証済みです。以前の形式は「非推奨 — 使用しないでください」に記載されています。
このスキルでは、すべての Unreal モジュールの基盤となる C++ レイヤーを扱います。リフレクションマクロ(UCLASS、UPROPERTY、UFUNCTION、USTRUCT、UENUM、UINTERFACE)、コンテナ、デリゲート、文字列型、オブジェクトのライフタイムとガベージコレクション、CDO アクセス、サブシステム群が含まれます。これらはすべて Core、CoreUObject、Engine モジュールに含まれます(PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine" });)。エディターサブシステムを使用するには、エディター専用モジュールに EditorSubsystem と UnrealEd も必要です。
コンテキスト
.agents/ue-project-context.md が存在する場合は読み込んでください(モジュール名、規約、有効なプラグイン、GAS/ネットワーキングの設定)。存在しなくても作業を中断しないでください。
依頼とコードベースから対象分野を特定してください。解釈が複数あり、それぞれで異なるコードになる場合に限り、質問してください。
| 依頼の内容… | 参照先 |
|---|---|
UCLASS、UPROPERTY、UFUNCTION、USTRUCT、UENUM の指定子 | リフレクションマクロ |
TArray、TMap、TSet、TOptional、TVariant | コンテナ |
デリゲート、イベント、AddDynamic、Broadcast | デリゲート |
FName、FString、FText、LOCTEXT | 文字列型 |
TObjectPtr、TWeakObjectPtr、TSharedPtr、GC ルート、FGCObject | オブジェクトのライフタイムとポインター |
クラスデフォルトオブジェクト、GetDefault、TNotNull パラメーター | CDO アクセスと非 null パラメーター |
| ゲームインスタンス/ワールド/ローカルプレイヤー/エンジン/エディターのサブシステム | サブシステム |
Replicated、ReplicatedUsing、GetLifetimeReplicatedProps | レプリケートされるプロパティ |
UE_LOG、ログカテゴリ | ロギング |
WITH_EDITOR、UE_BUILD_SHIPPING ガード | 条件付きコンパイルガード |
リフレクションマクロ
リフレクション対象の型では、ボディの最初の行に GENERATED_BODY() を置き、ヘッダーの最後の include として #include "TypeName.generated.h" を記述します。ゲームモジュール内のすべての UCLASS には、モジュール API マクロ(MYGAME_API)を付けます。指定子の解析では大文字と小文字は区別されません(エンジンのヘッダーでは config=Game と Config=Game の両方が使われています)。指定子と meta= の完全な一覧は、references/property-specifiers.md を参照してください。
UCLASS
| 指定子 | 効果 |
|---|---|
Blueprintable / BlueprintType | Blueprint でのサブクラス化/Blueprint の変数型としての使用を許可します(Not… 形式では禁止されます) |
Abstract | インスタンス化できません。サブクラスはインスタンス化できます |
Config=Game、DefaultConfig | UPROPERTY(Config) メンバーは DefaultGame.ini から読み込まれます。DefaultConfig は同ファイルへの保存も行います |
Transient | インスタンスは保存されません |
ClassGroup=Name + meta=(BlueprintSpawnableComponent) | コンポーネントが Add Component メニューに表示されます |
UPROPERTY
| グループ | 指定子 |
|---|---|
| エディターでの表示 | EditAnywhere、EditDefaultsOnly、EditInstanceOnly、VisibleAnywhere、VisibleDefaultsOnly、VisibleInstanceOnly、AdvancedDisplay |
| Blueprint アクセス | BlueprintReadWrite、BlueprintReadOnly、BlueprintGetter=Fn、BlueprintSetter=Fn、BlueprintAssignable(マルチキャストデリゲートのみ) |
| シリアライズ | Transient、DuplicateTransient、SaveGame、Config、GlobalConfig、Instanced、SkipSerialization、NonTransactional |
| レプリケーション | Replicated、ReplicatedUsing=OnRep_Fn、NotReplicated |
よく使われる meta= キー | ClampMin/ClampMax、UIMin/UIMax、EditCondition、EditConditionHides、AllowPrivateAccess、DisplayName、ToolTip、Units、AllowedClasses、MustImplement、ExposeOnSpawn、TitleProperty |
// MyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"
class UStaticMeshComponent;
class UStaticMesh;
UCLASS(Blueprintable)
class MYGAME_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Stats", meta=(ClampMin="1.0"))
float MaxHealth = 100.f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Stats")
float CurrentHealth = 100.f;
UPROPERTY(Transient)
TObjectPtr<UStaticMeshComponent> CachedMesh; // not serialized, still GC-tracked
UPROPERTY(EditDefaultsOnly, Category="Config")
TSubclassOf<AActor> ProjectileClass; // class reference restricted to AActor subclasses
UPROPERTY(EditDefaultsOnly, Category="Config")
TSoftObjectPtr<UStaticMesh> LazyMesh; // path reference; load on demand
UFUNCTION(BlueprintNativeEvent, Category="Combat")
void OnDamageTaken(float Amount);
virtual void OnDamageTaken_Implementation(float Amount);
};
UFUNCTION
| 指定子 | 効果 |
|---|---|
BlueprintCallable / BlueprintPure | 実行ピンあり/なしのノードです。BlueprintPure は状態を変更してはいけません |
BlueprintNativeEvent | Blueprint でオーバーライドできます。C++ のデフォルト実装本体は Name_Implementation です |
BlueprintImplementableEvent | Blueprint で実装します。C++ の実装本体はありません |
BlueprintAuthorityOnly / BlueprintCosmetic | Blueprint からの呼び出しは、ネットワーク権限がある場合のみ実行されます/専用サーバーでは実行されません(C++ から直接呼び出した場合はフィルタリングされません) |
Server、Client、NetMulticast と Reliable または Unreliable、WithValidation | RPC です。ルールと例については ue-networking-replication を参照してください |
Exec | コンソールコマンドです。コンソールは PlayerInput、PlayerController、Pawn、HUD、GameMode、CheatManager、GameState、PlayerCameraManager、GameInstance にルーティングします |
CallInEditor | Details パネルにボタンを追加します |
// MyCharacter.cpp — the only body a BlueprintNativeEvent gets in C++
void AMyCharacter::OnDamageTaken_Implementation(float Amount) { CurrentHealth = FMath::Max(0.f, CurrentHealth - Amount); }
関数ライブラリ、潜在ノードと非同期ノード、WorldContext/DefaultToSelf/ExpandEnumAsExecs、その他の Blueprint 向け meta= キーについては、ue-blueprint-cpp-interop を参照してください。
USTRUCT、UENUM、UINTERFACE
// MyTypes.h
#pragma once
#include "CoreMinimal.h"
#include "MyTypes.generated.h"
USTRUCT(BlueprintType)
struct MYGAME_API FMyWeaponStats
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon")
float BaseDamage = 10.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon")
float FireRate = 0.5f;
};
UENUM(BlueprintType)
enum class EMyWeaponState : uint8 // Blueprint-visible enums are enum class : uint8
{
Idle,
Firing UMETA(DisplayName="Firing Weapon"),
MAX UMETA(Hidden)
};
UDataTableの行型は、FTableRowBase(Engine/DataTable.h)を継承するUSTRUCTです。ue-data-assets-tablesを参照してください。- すべての
USTRUCTメンバーをクラス内で初期化してください。リフレクション対象の構造体は値型であり、エンジンによって自由にコピーされます。 - ポリモーフィックな構造体値(基底クラスから派生した任意の
USTRUCT)は、FInstancedStructまたは型付きのTInstancedStruct<FMyBase>(StructUtils/InstancedStruct.h、モジュールCoreUObject)として格納します。 UINTERFACEは、UInterfaceを継承するスタブUMyThingとIMyThingクラスを組み合わせます。指定子の表とネイティブの例は references/property-specifiers.md にあります。Blueprint で実装可能なインターフェースについては、ue-blueprint-cpp-interopを参照してください。
コンテナ
API 全般、反復処理、パフォーマンスに関する注意事項については、references/container-patterns.md を参照してください。UObject ポインターを格納するコンテナが GC の追跡対象になるのは、UPROPERTY() TArray<TObjectPtr<T>> の場合のみです(TMap/TSet も同様)。
TArray<FString> Names;
Names.Add(TEXT("Alpha"));
Names.Emplace(TEXT("Beta")); // construct in place
Names.Reserve(100); // pre-size before a known number of Adds
int32 Idx = Names.Find(TEXT("Beta")); // INDEX_NONE if absent
FString* Ptr = Names.FindByPredicate([](const FString& S) { return S.StartsWith(TEXT("A")); });
Names.Sort([](const FString& A, const FString& B) { return A.Len() < B.Len(); });
Names.Remove(TEXT("Alpha")); // order-preserving, O(n)
Names.RemoveAtSwap(0); // O(1), reorders
for (int32 i = Names.Num() - 1; i >= 0; --i) { if (Names[i].IsEmpty()) { Names.RemoveAt(i); } } // never mutate inside ranged-for
TMap<FName, int32> ItemCounts;
int32& Count = ItemCounts.FindOrAdd(FName("Sword")); // inserts default if absent
int32* Found = ItemCounts.Find(FName("Axe")); // nullptr if absent
for (const TPair<FName, int32>& Pair : ItemCounts) { UE_LOG(LogMyGame, Log, TEXT("%s x%d"), *Pair.Key.ToString(), Pair.Value); }
TSet<FName> Tags;
Tags.Add(FName("Flying"));
bool bFlying = Tags.Contains(FName("Flying")); // hashed, no duplicates
TOptional<float> MaybeHP;
float Safe = MaybeHP.Get(0.f); // default when unset
TVariant
#include "Misc/TVariant.h"
#include <type_traits>
TVariant<int32, float, FString> Value; // first type must be default-constructible (or use FEmptyVariantState)
Value.Set<FString>(TEXT("Hello"));
if (const FString* Str = Value.TryGet<FString>()) { UE_LOG(LogMyGame, Log, TEXT("%s"), **Str); }
Visit([](auto& Held) // one generic lambda; branch with if constexpr
{
using HeldType = std::decay_t<decltype(Held)>;
if constexpr (std::is_same_v<HeldType, FString>) { UE_LOG(LogMyGame, Log, TEXT("%s"), *Held); }
}, Value);
デリゲート
宣言マクロ、バインドメソッド、ペイロードのルールについては、references/delegate-patterns.md を参照してください。
| マクロファミリー | バインディング数 | Blueprint | 用途 |
|---|---|---|---|
DECLARE_DELEGATE(_RetVal、_OneParam …) | 1 | いいえ | 単一オーナーのコールバック。値を返すこともできます |
DECLARE_MULTICAST_DELEGATE | N | いいえ | C++ イベント(別スレッド用には DECLARE_TS_…) |
DECLARE_DYNAMIC_DELEGATE | 1 | はい | Blueprint に割り当て可能なコールバック(UFUNCTION ターゲットのみ) |
DECLARE_DYNAMIC_MULTICAST_DELEGATE | N | はい | UPROPERTY(BlueprintAssignable) イベント |
// MyHealthComponent.h — delegate types are declared at file scope, above the UCLASS
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnMyHealthChangedNative, float /*Current*/, float /*Max*/);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnMyHealthChanged, float, CurrentHealth, float, MaxHealth);
// in UMyHealthComponent : public UActorComponent
UPROPERTY(BlueprintAssignable, Category="Health")
FOnMyHealthChanged OnHealthChanged; // dynamic: needs UPROPERTY, params need names
FOnMyHealthChangedNative OnHealthChangedNative; // native: no reflection, cheaper to broadcast
// in AMyListenerActor : public AActor
UFUNCTION() // AddDynamic targets must be UFUNCTIONs
void HandleHealthChanged(float CurrentHealth, float MaxHealth);
void HandleHealthChangedNative(float Current, float Max);
UPROPERTY() TObjectPtr<UMyHealthComponent> Health;
FDelegateHandle NativeHandle;
// AMyListenerActor.cpp — bind in BeginPlay (after Super::), unbind in EndPlay (before Super::)
Health->OnHealthChanged.AddDynamic(this, &AMyListenerActor::HandleHealthChanged);
NativeHandle = Health->OnHealthChangedNative.AddUObject(this, &AMyListenerActor::HandleHealthChangedNative);
// EndPlay: guard with IsValid(Health) first
Health->OnHealthChanged.RemoveDynamic(this, &AMyListenerActor::HandleHealthChanged);
Health->OnHealthChangedNative.Remove(NativeHandle);
オーナーは OnHealthChanged.Broadcast(CurrentHealth, MaxHealth); でブロードキャストします。両方のクラス全体は、references/delegate-patterns.md を参照してください。
単一デリゲートは BindUObject、BindSP、BindRaw、BindStatic、BindLambda、BindWeakLambda(this, ...) でバインドし、ExecuteIfBound(...) で実行します。this をキャプチャするラムダには、オブジェクトとともにバインディングが破棄されるよう、AddWeakLambda/BindWeakLambda を優先してください。
文字列型
| 型 | 用途 | 比較 | 備考 |
|---|---|---|---|
FName | 識別子、アセット名、ボーン名、タグ | 整数による O(1)、大文字と小文字を区別しない | グローバルテーブルにインターン化されます。不変です |
FString | パス、解析、実行時に生成するテキスト | O(n) | 可変のヒープ文字列です。*Str は const TCHAR* を返します |
FText | プレイヤーが読むすべてのテキスト | — | ローカライズ可能です。LOCTEXT/NSLOCTEXT/FText::Format で構築します |
float Health = 42.f; int32 Current = 3; int32 Max = 5;
FName Tag(TEXT("Weapon.Rifle"));
FString S = Tag.ToString();
FName Back = FName(*S);
FString Msg = FString::Printf(TEXT("HP: %.1f (%d/%d)"), Health, Current, Max);
int32 Parsed = FCString::Atoi(TEXT("42"));
#define LOCTEXT_NAMESPACE "MyGame"
FText Label = LOCTEXT("RifleName", "Assault Rifle");
FText Fmt = FText::Format(LOCTEXT("HPFmt", "HP: {0}/{1}"), FText::AsNumber(Current), FText::AsNumber(Max));
#undef LOCTEXT_NAMESPACE
FText Other = NSLOCTEXT("MyGame", "Key", "Text"); // no #define needed
FText Raw = FText::FromString(S); // not localized; runtime-generated text only
オブジェクトのライフタイムとポインター
ガベージコレクターは、ルートからリフレクションされた(UPROPERTY)参照、FGCObject の参照元、TStrongObjectPtr、およびルート化されたオブジェクトを通じて到達可能なすべての UObject を生存状態に保ちます。GC から見えないポインターは、ダングリングする可能性があります。
// Reflected members: TObjectPtr — GC-tracked, access-tracked in the editor, used like a raw pointer
UPROPERTY() TObjectPtr<UStaticMeshComponent> MeshComp;
// Legacy APIs that want raw pointers
void FillObjects(TArray<UObject*>& Out);
TArray<TObjectPtr<UObject>> Objects;
FillObjects(MutableView(Objects)); // temporary TArray<UObject*>& view; ToRawPtr(Ptr) for a single read-only copy
// Non-owning reference: TWeakObjectPtr becomes null once the object is destroyed or collected
TWeakObjectPtr<AMyCharacter> WeakTarget;
if (AMyCharacter* Target = WeakTarget.Get()) { Target->OnDamageTaken(5.f); }
// Keep-alive from non-reflected code: scoped root instead of AddToRoot()/RemoveFromRoot()
TStrongObjectPtr<UMyDataObject> Pinned(NewObject<UMyDataObject>());
// Plain C++ types only: never wrap a UObject in TSharedPtr/TUniquePtr
struct FMyData { int32 Score = 0; };
TSharedPtr<FMyData> Data = MakeShared<FMyData>();
TWeakPtr<FMyData> WeakData = Data; // Pin() returns a TSharedPtr if still alive
UObject を保持する UObject 以外のクラスは FGCObject を継承し、TObjectPtr メンバーを通じてそれらを報告します。AddReferencedObject(s) の生の UObject* オーバーロードは非推奨であり、インクリメンタル GC では安全ではありません。
#include "UObject/GCObject.h"
class FMyManager : public FGCObject
{
public:
virtual void AddReferencedObjects(FReferenceCollector& Collector) override { Collector.AddReferencedObject(ManagedObject); }
virtual FString GetReferencerName() const override { return TEXT("FMyManager"); }
private:
TObjectPtr<UMyDataObject> ManagedObject; // TObjectPtr<T>& overload; raw UObject* is deprecated
};
CDO アクセスと非 null パラメーター
#include "Misc/NotNull.h"
const UMyDataObject* Defaults = GetDefault<UMyDataObject>(); // class default object, read-only
UMyDataObject* Settings = GetMutableDefault<UMyDataObject>(); // settings-style objects
UClass* SomeClass = AMyCharacter::StaticClass();
const AMyCharacter* ClassCDO = SomeClass->GetDefaultObject<AMyCharacter>(); // CDO of a runtime UClass
// TNotNull<T*>: caller cannot pass null; checked at the call site in Debug/Development, a plain pointer in Test and Shipping
void RegisterOwner(TNotNull<AActor*> Owner);
void RegisterOwner(TNotNull<AActor*> Owner)
{
Owner->SetActorHiddenInGame(false); // no null check needed inside
}
UClass::ClassDefaultObject の直接アクセスは非推奨です。TNotNull<T*> は暗黙的に T* に変換されます。null が意味のある値である場合は、T* を使用してください。
サブシステム
エンジンオブジェクトが所有する、自動インスタンス化されるシングルトンです。手動でルート化する必要はありません。Initialize(FSubsystemCollectionBase&)/Deinitialize() をオーバーライドします。順序が重要な場合は、Initialize 内で Collection.InitializeDependency<UMyOtherSubsystem>() を呼び出します。対象外にするには、ShouldCreateSubsystem(UObject* Outer) const から false を返します。
| クラス | ヘッダー | 所有者/ライフタイム | アクセサー |
|---|---|---|---|
UEngineSubsystem | Subsystems/EngineSubsystem.h | UEngine;プロセス全体 | GEngine->GetEngineSubsystem<T>() |
UGameInstanceSubsystem | Subsystems/GameInstanceSubsystem.h | UGameInstance;マップ変更後も存続 | GetGameInstance()->GetSubsystem<T>() |
UWorldSubsystem | Subsystems/WorldSubsystem.h | UWorld;ワールドごとに再作成されます。DoesSupportWorldType でフィルタリングします | GetWorld()->GetSubsystem<T>() |
UTickableWorldSubsystem | Subsystems/WorldSubsystem.h | 上記に加えて Tick() を実行します。GetStatId() の実装が必要です | GetWorld()->GetSubsystem<T>() |
ULocalPlayerSubsystem | Subsystems/LocalPlayerSubsystem.h | ULocalPlayer;ローカルプレイヤーごとに 1 つ | LocalPlayer->GetSubsystem<T>()、ULocalPlayer::GetSubsystemFromController<T>(PC) |
UEditorSubsystem | EditorSubsystem.h(モジュール EditorSubsystem) | UEditorEngine;エディターセッション中のみ | GEditor->GetEditorSubsystem<T>() |
// MyInventorySubsystem.h
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyInventorySubsystem.generated.h"
UCLASS()
class MYGAME_API UMyInventorySubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
UFUNCTION(BlueprintCallable, Category="Inventory")
void AddItem(FName ItemID, int32 Count);
private:
TMap<FName, int32> Inventory;
};
// A ticking world subsystem adds these; Initialize/Deinitialize must call Super:: (the base registers the ticker)
UCLASS()
class MYGAME_API UMyTickableSubsystem : public UTickableWorldSubsystem
{
GENERATED_BODY()
public:
virtual void Tick(float DeltaTime) override;
virtual TStatId GetStatId() const override { RETURN_QUICK_DECLARE_CYCLE_STAT(UMyTickableSubsystem, STATGROUP_Tickables); }
virtual bool DoesSupportWorldType(const EWorldType::Type WorldType) const override; // e.g. Game and PIE only
};
// Access from an AActor member function
UMyInventorySubsystem* Inv = GetGameInstance()->GetSubsystem<UMyInventorySubsystem>();
UMyTickableSubsystem* Tck = GetWorld()->GetSubsystem<UMyTickableSubsystem>();
APlayerController* PC = GetWorld()->GetFirstPlayerController();
UMyUISubsystem* UI = ULocalPlayer::GetSubsystemFromController<UMyUISubsystem>(PC); // null-safe
UMyEngineSubsystem* Eng = GEngine->GetEngineSubsystem<UMyEngineSubsystem>();
UWorldSubsystem では、PostInitialize()、OnWorldBeginPlay(UWorld& InWorld)、OnWorldEndPlay(UWorld& InWorld)、OnWorldComponentsUpdated(UWorld& World) もオーバーライドできます。ULocalPlayerSubsystem::GetLocalPlayer<T>() と UGameInstanceSubsystem::GetGameInstance() は所有者を返します。
レプリケートされるプロパティ
指定子と GetLifetimeReplicatedProps のエントリーの両方が必要です。条件(COND_*)、RPC のルール、プッシュモデル、Iris については、ue-networking-replication を参照してください。
// MyReplicatedActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyReplicatedActor.generated.h"
UCLASS()
class MYGAME_API AMyReplicatedActor : public AActor
{
GENERATED_BODY()
public:
AMyReplicatedActor() { bReplicates = true; }
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
protected:
UPROPERTY(ReplicatedUsing=OnRep_Health)
float Health = 100.f;
UFUNCTION()
void OnRep_Health(); // runs on clients after Health changes
};
// MyReplicatedActor.cpp
#include "MyReplicatedActor.h"
#include "Net/UnrealNetwork.h" // required for DOREPLIFETIME
void AMyReplicatedActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyReplicatedActor, Health);
}
void AMyReplicatedActor::OnRep_Health() {}
ロギング
DECLARE_LOG_CATEGORY_EXTERN(LogMyGame, Log, All); // MyGame.h (module header)
DEFINE_LOG_CATEGORY(LogMyGame); // MyGame.cpp
UE_LOG(LogMyGame, Warning, TEXT("HP low: %.1f"), 12.5f);
詳細度(Logging/LogVerbosity.h):Fatal、Error、Warning、Display、Log、Verbose、VeryVerbose。Display はコンソールとログファイルに出力し、Log はログファイルのみに出力します。Shipping ビルドでは、ターゲットで bUseLoggingInShipping = true を設定しない限り、UE_LOG はコンパイル時に除外されます。カテゴリ、構造化ロギング(UE_LOGFMT)、実行時の詳細度制御、プロファイリングについては、ue-testing-debugging を参照してください。
条件付きコンパイルガード
#if WITH_EDITORONLY_DATA
UPROPERTY(EditAnywhere, Category="Debug")
bool bShowDebugSpheres = false; // reflected editor-only data
#endif
#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; // editor-only code
#endif
#if !UE_BUILD_SHIPPING
void DrawDebugInfo(); // Debug, Development and Test only
#endif
非推奨 — 使用しないでください
| 使用しない | 5.8 で使用 | 出典 |
|---|---|---|
SomeClass->ClassDefaultObject | GetDefault<T>()、GetMutableDefault<T>()、SomeClass->GetDefaultObject<T>() | UObject/Class.h:4045 の UE_DEPRECATED(5.6) |
UObject* メンバーでの Collector.AddReferencedObject(RawUObjectPtr) | AddReferencedObject(s) に渡す TObjectPtr<T> メンバー | UObject/UObjectGlobals.h:109 の UE_REFERENCE_COLLECTOR_REQUIRE_OBJECTPTR_DEPRECATED による UE_DEPRECATED(5.3) |
可変配列での ToRawPtrArrayUnsafe(Array)、ToRawPtrTArrayUnsafe(Array) | MutableView(Array)、または TArray<TObjectPtr<T>> のままにする | UObject/ObjectPtr.h:1112,1156 の UE_DEPRECATED(5.6) |
Visit(<overload-set helper struct>{...}, Variant) | if constexpr (std::is_same_v<...>) を使った単一のジェネリックラムダ | ヘルパーは Lyra のサンプルコードであり、5.8 のヘッダーにはありません(Misc/TVariant.h) |
GENERATED_USTRUCT_BODY()、GENERATED_UCLASS_BODY()、GENERATED_IINTERFACE_BODY() | GENERATED_BODY() | UObject/ObjectMacros.h:802-805 のレガシーエイリアス |
一時的な生存維持のための Obj->AddToRoot()/RemoveFromRoot() | TStrongObjectPtr<T>(UObject/StrongObjectPtr.h) | Root 登録は解除されるまで永続します。スコープ付きポインターならリークしません |
TMap::TIterator(Map, /*bRequiresRehashOnRemoval*/ true)(削除後に自動で Relax) | Map.CreateIterator()。必要に応じて、自分で Compact()/Shrink() を呼び出します | Containers/Map.h.inl:916 の UE_DEPRECATED(5.8)。TSet::Relax() 自体にはまだマークされていません(Containers/SparseSet.h.inl:319) |
TIsConst<T>、TIsMemberPointer<T> | std::is_const_v<T>、std::is_member_pointer_v<T> | Templates/IsConst.h:15 の UE_DEPRECATED(5.7)、Templates/IsMemberPointer.h:14 の UE_DEPRECATED(5.8) |
FThreadSafeRefCountedObject、FRefCountBase | FRefCountedObject(現在はスレッドセーフ) | Templates/RefCounting.h:151-153 の UE_DEPRECATED(5.8) |
FCoreDelegates::OnPostEngineInit.AddRaw(...) | FCoreDelegates::GetOnPostEngineInit().AddRaw(...) | Misc/CoreDelegates.h:240 の UE_DEPRECATED(5.8) |
Delegate.ProcessMulticastDelegate<UObject>(Params) | Delegate.ProcessDelegate<UObject>(Params) | UObject/ScriptDelegates.h:1462 の UE_DEPRECATED(5.8) |
meta=(HideAssetPicker) | meta=(HidePinAssetPicker) | UObject/ObjectMacros.h:1673 の UE_DEPRECATED(5.6) |
ObjPtr.IsRemote() | ObjPtr.GetResidence() | UObject/ObjectPtr.h:206 の UE_DEPRECATED(5.8) |
よくある間違い
UPROPERTY のない生の UObject* メンバー — GC 後にダングリングします:
UMyDataObject* Obj; // WRONG: invisible to GC
UPROPERTY() TObjectPtr<UMyDataObject> Obj; // RIGHT
範囲ベースの for ループ内で TArray を変更する — イテレーターが無効になります:
TArray<AActor*> Actors;
for (AActor* A : Actors) { Actors.Remove(A); } // WRONG
for (int32 i = Actors.Num() - 1; i >= 0; --i) { if (!IsValid(Actors[i])) { Actors.RemoveAt(i); } } // RIGHT
UObject を TSharedPtr でラップする — 所有者が二つになり、クラッシュします: UObject は GC が所有します。TObjectPtr、TWeakObjectPtr、または TStrongObjectPtr を使用してください。
.generated.h が最後のインクルードではない、または MYGAME_API がない: UnrealHeaderTool がヘッダーを拒否します。API マクロがないと、後に別のモジュールから LNK2019 が発生します。
非 UFUNCTION にバインドされた AddDynamic: リフレクション検索が実行時に失敗し、ハンドラーが実行されません。UFUNCTION() を付けてください。
.cpp の定義の上に UPROPERTY/UFUNCTION を記述する: UnrealHeaderTool が解析するのはヘッダーだけなので、マクロは無視されます。クラス本体内の宣言に付けてください。
Name_Implementation のない BlueprintNativeEvent: リンク時に未解決の外部シンボルになります。virtual void Name_Implementation(...) を宣言して定義してください。
Super:: を呼び出さない UTickableWorldSubsystem::Initialize/Deinitialize のオーバーライド: ティック登録は基底クラスの実装内にあります。サブシステムはティックされません。
ClassDefaultObject を直接読み取る: 非推奨であり、まもなく private になります。GetDefault<T>() を使用してください。
Log の詳細度が「表示されない」: Log は仕様上ファイルにのみ出力されます。コンソールに出力するには Display を使用してください。
関連するスキル
ue-actor-component-architecture— AActor/UActorComponent のライフサイクル、スポーン、ティックグループ、コンポーネントのセットアップue-module-build-system— Build.cs、モジュールの依存関係、API エクスポートマクロ、インクルードパス、PCHue-testing-debugging— ログカテゴリと詳細度、構造化ログ、オートメーションテスト、プロファイリングue-networking-replication— DOREPLIFETIME の条件、RPC のルール、プッシュモデル、Irisue-blueprint-cpp-interop— UBlueprintFunctionLibrary、潜在アクションと非同期アクション、Blueprint で実装可能- 関連項目:
ue-data-assets-tables、ue-animation-system、ue-async-threading、ue-audio-system、ue-editor-tools、ue-gameplay-abilities、ue-gameplay-framework、ue-gameplay-tags-messaging、ue-input-system、ue-mass-entity、ue-materials-rendering、ue-serialization-savegames、ue-state-trees、ue-ui-umg-slate、ue-world-level-streaming