コンポーネント は、アクタ がサブオブジェクトとして自身にアタッチできるアタッチできる特別なタイプの オブジェクト です。視覚的表現の表示、サウンドの再生など一般的なビヘイビアを共有するうえで役立ちます。また、コンポーネントは、車両が入力を解釈して自身の速度と方向を変更する方法など、プロジェクト固有の概念を表すこともできます。例えば、ユーザー制御が可能な車、航空機、ボートを使用するプロジェクトでは、車両アクタが使用するコンポーネントを変更することで、車両の制御と動きの違いを実装できます。
Actor コンポーネント
UActorComponent
はすべてのコンポーネントの基本クラスです。コンポーネントはメッシュと画像のレンダリング、コリジョンの実装、音声再生を行う唯一の手段であるため、ゲームをプレイするときにプレイヤーがワールドで見たり、やり取りしたりするものはすべて、最終的にはいずれかのタイプのコンポーネントの動作になります。
独自のコンポーネント (Actor コンポーネント、Scene コンポーネント、および Primitive コンポーネント を作成する際には、理解しておく必要のある主要なクラスがいくつかあります。
-
Actor コンポーネント (
UActorComponent
クラス) は、移動、インベントリ、または属性管理、およびその他の非物理的概念などの抽象的なビヘイビアで最も役立ちます。Actor コンポーネントにはトランスフォームは含まれません。つまり、ワールド内での物理的な位置や回転は含んでいません。 -
Scene コンポーネント (
USceneComponent
クラス、UActorComponent
の子) はジオメトリ表現を必要としない場所ベースのビヘイビアをサポートします。これには、スプリング アーム、カメラ、物理的な力、およびコンストレイント (物理オブジェクトは除く)、さらには音声が含まれます。 -
Primitive コンポーネント (
UPrimitiveComponent
クラス、USceneComponent` の子) ジオメトリ表現を備えた Scene コンポーネントです。これは、通常、ビジュアル要素のレンダリング、または物理オブジェクトとのコリジョンまたはオーバーラップに使用されます。これには、スタティック メッシュまたはスケルタル メッシュ、スプライトまたはビルボード、パーティクル システム、ボックス、カプセル、球体のコリジョン ボリュームが含まれます。
コンポーネントの登録
Actor コンポーネントが各フレームを更新してシーンに反映させるには、Engine で Actor コンポーネントを 登録する 必要があります。登録は、アクタのスポーン プロセス中に、アクタのサブオブジェクトとして作成されたコンポーネントに対して自動的に行われます。ただし、プレイ中に作成されたコンポーネントは手動で登録できます。RegisterComponent
関数は、コンポーネントがアクタに関連付けられていることを条件として、この機能を提供します。
プレイ中にコンポーネントを登録すると、パフォーマンスに影響することがあるため、プレイ中の登録は必要な場合に限り行ってください。
登録イベント
コンポーネントを登録するプロセスでは、Engine がコンポーネントをシーンに関連付けて、そのコンポーネントをフレームごとの更新で利用可能にし、さらに次の UActorComponent
関数を実行します。
関数 | 説明 |
---|---|
OnRegister |
この関数をオーバーライドすることで、コンポーネントを登録するときにコードを追加できます。 |
CreateRenderState |
コンポーネントの レンダリング ステート を初期化します。 |
OnCreatePhysicsState |
コンポーネントの 物理ステート を初期化します。 |
コンポーネントの登録を解除する
更新、シミュレーション、またはレンダリングの各プロセスから Actor コンポーネントを削除するには、UnregisterComponent
関数でそのコンポーネントの登録を解除することができます。
イベントの登録を解除する
コンポーネントの登録を解除するには、次の UActorComponent
関数を実行します。
関数 | 説明 |
---|---|
OnUnregister |
この関数をオーバーライドすることで、コンポーネントの登録を解除するときにコードを追加できます。 |
DestroyRenderState |
コンポーネントのレンダリング ステートを初期化前の状態に戻します。 |
OnDestroyPhysicsState |
コンポーネントの物理ステートを初期化前の状態に戻します。 |
更新
Actor コンポーネントには、アクタと同様の方法で各フレームを更新する機能があります。TickComponent
関数を使用すると、コンポーネントによって各フレームでコードを実行できます。例えば、USkeletalMeshComponent はその TickComponent
関数を使用して、アニメーションやスケルタル コントローラーを更新し、UParticleSystemComponent ではそのエミッタを更新して、パーティクル イベントを処理します。
デフォルトでは、Actor コンポーネントは更新を行いません。Actor コンポーネントに各フレームを更新させるには、コンストラクタで PrimaryComponentTick.bCanEverTick
を true
に設定して、ティックを有効にする必要があります。その後、コンストラクタまたはそれ以外の場所で、PrimaryComponentTick.SetTickFunctionEnable(true)
を呼び出して更新を有効にする必要があります。後に PrimaryComponentTick.SetTickFunctionEnable(false)
を呼び出して、ティックを無効にすることもできます。コンポーネントを更新する必要がまったくないことがわかっている場合、または (多くの場合所有している Actor クラスから) 独自の更新関数を手動で呼び出す場合は、PrimaryComponentTick.bCanEverTick
をデフォルトの false
ままにすると、若干パフォーマンスが向上します。
レンダリング ステート
レンダリングするには、Actor コンポーネントでレンダリング ステートを作成する必要があります。また、このレンダリング ステートは、レンダリング データの更新が必要なコンポーネントについて何らかの変更があった場合に Engine に通知します。このような変更が発生すると、レンダリング ステートは「ダーティ」とマークされます。独自のコンポーネントを作成する場合は、MarkRenderStateDirty
関数を使用してレンダリング データをダーティとしてマークできます。フレームの末尾では、すべてのダーティ コンポーネントのレンダリング データが Engine で更新されます。Scene コンポーネント (Primitive コンポーネントを含む) はデフォルトでレンダリング ステートを作成しますが、Actor コンポーネントは作成しません。
物理ステート
Actor コンポーネントを Engine の物理シミュレーション システムで使用するには、Actor コンポーネントに物理ステートが必要です。物理ステートは変更が発生するとすぐに更新され、「フレーム遅延」アーティファクトなどの問題を防ぎ、「ダーティ」マーカーの必要性を排除します。デフォルトでは、Actor コンポーネントおよび Scene コンポーネントには物理ステートがありませんが、Primitive コンポーネントにはあります。Component クラスのインスタンスに物理ステートが必要かどうかを判断するためには、ShouldCreatePhysicsState
関数をオーバーライドします。
クラスで物理を使用する場合、単に true
を返すことは推奨しません。コンポーネントの破壊中など、物理ステートを作成してはならない一部の状況については、関数の UPrimitiveComponent
バージョンを参照してください。また、通常であれば true
を返す場合に、Super::ShouldCreatePhysicsState
を返すこともできます。
Visualization コンポーネント
一部のアクタとコンポーネントには視覚表現がないため、選択が困難であったり、重要なプロパティが表示されなかったりします。デベロッパーは、Editor での作業中に、情報を表示するためのコンポーネントを追加できますが、このような追加コンポーネントは、Play In Editor 時やパッケージ ビルドの実行中には不要です。。これに対処するために、Editor では Visualization コンポーネント の概念をサポートしています。このコンポーネントは、Editor で作業しているときにのみ存在する通常のコンポーネントです。
Visualization コンポーネントを作成するには、通常のコンポーネントを作成して、それに対して SetIsVisualizationComponent
を呼び出します。このコンポーネントは Editor の外部で存在する必要がないため、このコンポーネントへのすべての参照は、WITH_EDITORONLY_DATA
または WITH_EDITOR
に対するプリプロセッサ チェック内に記載する必要があります。これにより、パッケージ化されたビルドがこれらのコンポーネントの影響を受けず、コード内のどの場所でもこれらのコンポーネントを参照しないことが保証されます。例として、Camera コンポーネント は、ビューの視錐台を表示する Draw Frustum コンポーネント など、他の複数のコンポーネントを使用して、役立つ情報を Editor に表示します。ヘッダ ファイルでは、Draw Frustum コンポーネントがクラス内で次のように定義されています。
#if WITH_EDITORONLY_DATA
// The frustum component used to show visually where the camera field of view is
class UDrawFrustumComponent* DrawFrustum;
// ...
#endif
同様に、このコンポーネントへのすべての参照は、ソース ファイルの WITH_EDITORONLY_DATA
に対するプリプロセッサ チェック内に記載する必要があります。OnRegister
内の WITH_EDITORONLY_DATA
チェック内では、このコードは Camera コンポーネントが有効なアクタに接続されているかどうかを確認し、Draw Frustum コンポーネントのコードを追加します。
void UCameraComponent::OnRegister()
{
#if WITH_EDITORONLY_DATA
if (AActor* MyOwner = GetOwner())
{
// ...
if (DrawFrustum == nullptr)
{
DrawFrustum = NewObject<UDrawFrustumComponent>(MyOwner, NAME_None, RF_Transactional | RF_TextExportTransient);
DrawFrustum->SetupAttachment(this);
DrawFrustum->SetIsVisualizationComponent(true);
// ...
}
}
// ...
#endif
Super::OnRegister();
// ...Additional code (to run in all builds) goes here ...
}
DrawFrustum
は現在エディタ内にのみ存在し、Visualization コンポーネントと見なされます。つまり、Editor 内でのプレイテスト中は表示されません。
Scene コンポーネント
Scene コンポーネントはワールド内の特定の物理位置に存在する Actor コンポーネントです。この位置は、トランスフォーム (FTransform
クラス) によって定義されます。これには、コンポーネントの位置、回転状態、スケールが含まれます。Scene コンポーネントには、相互にアタッチすることでツリーを形成する機能があり、アクタは単一の Scene コンポーネントを「ルート」として指定できます。つまり、アクタのワールドの位置、回転状態、およびスケールがそのコンポーネントから描画されます。
アタッチメント
相互にアタッチ可能なのは Scene コンポーネント (USceneComponent
とその子クラス) のみです。これは、子コンポーネントと親コンポーネント間の空間的な関係性を記述するためにトランスフォームが必要であるためです。Scene コンポーネントは子をいくつでも持つことができますが、持つことができる親は 1 つだけです。また、Scene コンポーネントはワールドに直接配置することができます。Scene コンポーネント システムは、アタッチメント サイクルをサポートしていません。2 つの主要なメソッドは、未登録のコンポーネントを処理する場合とコンストラクタ内で役立つ SetupAttachment
と、1 つの Scene コンポーネントを別のものに迅速にアタッチし、プレイ中に役立つ AttachToComponent
です。このアタッチメント システムでは、特定のアクタのルート コンポーネントを別のアクタに属するコンポーネントにアタッチすることで、アクタを相互にアタッチすることもできます。
Primitive コンポーネント
Primitive コンポーネント (UPrimitiveComponent
クラス) は、通常レンダリングまたはコリジョンを目的として、ある種のジオメトリを格納または生成する Scene コンポーネントです。さまざまなタイプのジオメトリに複数のサブクラスがありますが、最も一般的なのは、Box コンポーネント、Capsule コンポーネント、Static Mesh コンポーネント、および Skeletal Mesh コンポーネント です。Box コンポーネントと Capsule コンポーネントは、コリジョン検出用の非表示のジオメトリを生成します。また、Static Mesh コンポーネントと Skeletal Mesh コンポーネントは、レンダリングされているビルド済みジオメトリを含み、必要に応じてコリジョン検出にも使用できます。
Scene Proxy
Primitive コンポーネントの Scene Proxy (FPrimitiveSceneProxy
クラス) は、Engine がコンポーネントをゲーム スレッドと並行してレンダリングするために使用するシーン データをカプセル化します。各タイプのプリミティブには、必要な特定のレンダリング データを保持するための独自の Scene Proxy 子クラスがあります。
プリミティブとレンダリング ジオメトリの詳細については、「レンダリング システムの概要」を参照してください。