コンポーネント
コンポーネントはノードにアタッチする C# クラスです。ノードは物がどこにあるかを持ち、コンポーネントはそれが何でどう振る舞うかを決めます。
コンポーネントの宣言
Component を継承し、引数のない public コンストラクターを持たせます(既定のもので十分です):
namespace Usercode;
public class Health : Component
{
public int maximum = 100;
public int Current { get; private set; }
public override void OnStart() => Current = maximum;
public void Damage(int amount)
{
Current = Math.Max(0, Current - amount);
if (Current == 0) Node!.IsActive = false;
}
}
宣言したコンポーネントはすべて Inspector の Add Component メニューに表示されます。[ComponentContextMenu("Gameplay/Health")] でパスの下にまとめられます。
コンポーネントの型は、シーンファイルでは安定した id で識別されます。スクリプトの場合、この id はスクリプトの .cs.meta ファイルから来ます(最初のコンパイル時に自動で作られます)。エンジンの型は [TypeId("…")] で宣言します。どちらの場合も、クラス名や名前空間を変えても保存済みのシーンは壊れません。
ライフサイクル
| コールバック | タイミング |
|---|---|
OnAttached() |
コンポーネントがノードにアタッチされた直後。 |
OnAwake() |
初回のアタッチ時に一度 — 非アクティブでも。サービスの取得はここで。 |
OnEnable() |
コンポーネントがアクティブになったとき。アクティブで開始する場合は OnAwake の直後にも。 |
OnStart() |
コンポーネントがアクティブな最初のフレームで一度、最初の更新の前に。 |
OnFixedUpdate(float fixedDeltaTime) |
60 Hz の固定ステップで、経過時間に応じた回数。 |
OnUpdate(float deltaTime) |
毎フレーム一度。 |
OnLateUpdate(float deltaTime) |
毎フレーム一度、すべての OnUpdate の後 — 動く物を追うカメラ向け。 |
OnDisable() |
コンポーネントまたはそのノードが非アクティブになったとき。 |
OnDetached() |
コンポーネントがノードから外れる直前。 |
OnDestroy() |
コンポーネントが削除されたか、ノードが破棄されたとき。 |
エンジンは毎フレーム、まだ開始していないコンポーネントを開始し、固定ステップを実行し、ツリー全体の OnUpdate、続いて OnLateUpdate を実行します。非アクティブなノードとコンポーネントはスキップされます。コンポーネントが投げた例外はコンポーネント名付きでログに記録され、ゲームは止まりません。
アクティブ化
component.IsActive は 1 つのコンポーネントを切り替えます。node.IsActive はノードを切り替えます。そのコンポーネントは OnEnable/OnDisable を受け取り、非アクティブな間、エンジンはそのノードとすべての子孫をスキップします。
他のコンポーネントとのやり取り
var health = Node!.GetComponent<Health>(); // 同じノード上、なければ null
var all = Node.GetComponents<LightComponent>(); // ノード上のすべて
var inChildren = Node.GetComponentsInChildren<Health>(); // ノードとその子孫
bool hasCamera = Node.HasComponent<CameraComponent>();
var light = Node.AddComponent<LightComponent>(); // 実行時にアタッチ
Node.RemoveComponent(light);
別のノードのコンポーネントを指すには、ComponentRef<T> フィールドを公開して Inspector でノードをドラッグし、実行時に Resolve(シーンのルート) を呼びます。ノードには NodeRef<Node> を使います。
エンジンのサービス
スクリプトは RuntimeServices を通してエンジンのサービスにアクセスします。Play Mode でもエクスポートしたゲームでも同じように動きます:
ISceneManager? scenes;
public override void OnAwake() => scenes = RuntimeServices.TryGet<ISceneManager>();
スクリプトで使えるサービス:ISceneManager(シーン)、IAssetLoader(アセット)、IInputSource と InputActionService(入力)、LocaleService(ローカライゼーション)。静的ファサード Input、InputActions、Localization がよく使う呼び出しをまとめています。
属性
| 属性 | 対象 | 効果 |
|---|---|---|
[ComponentContextMenu("パス/名前")] |
クラス | Add Component メニューでの位置を決めます。 |
[DisallowMultipleComponent] |
クラス | 1 ノードに 1 つまで。 |
[RequireComponent(typeof(T))] |
クラス | このコンポーネントを追加すると T も追加されます。 |
[Hide] |
メンバー | public メンバーを Inspector から隠します。 |
[Show] |
メンバー | public でないメンバーを表示します。 |
[ReadOnly] |
メンバー | 値を表示し、編集はさせません。 |
[Range(min, max)] |
数値 | 編集を範囲内に制限します。 |
[NumericUpDown] |
数値 | 上下ボタン付きのフィールドで表示します。 |
[Button] |
メソッド | 引数なしのメソッドを呼ぶボタンを表示します。 |
[Expand(false)] |
メンバー | グループを折りたたんだ状態で始めます。 |
[EnumLabel("…")] |
列挙値 | ドロップダウンのラベルを置き換えます。 |
ログ
Log.Logger は標準の Microsoft.Extensions.Logging の ILogger です:
Log.Logger.LogInformation("{Item} を拾った", item.Name);
Log.Logger.LogWarning("体力が少ない: {Current}", Current);
メッセージは Studio の Output パネル と実行中のゲームのコンソールに表示されます。
組み込みコンポーネント
| コンポーネント | メニュー | 用途 |
|---|---|---|
CameraComponent |
Rendering/Camera | 透視投影または平行投影のビュー。アクティブなカメラのうち Priority が最も高いものが描画します。 |
FreeFlyCameraComponent |
Rendering/Camera/Free Fly | WASD + マウスで飛ぶカメラ。 |
FpsCameraComponent |
Rendering/Camera/FPS | 一人称の視点と移動。 |
OrbitCameraComponent |
Rendering/Camera/Orbit | 対象点の周りを周回。ホイールでズーム。 |
FollowCameraComponent |
Rendering/Camera/Follow | 対象ノードをオフセット付きで追従。 |
LightComponent |
Rendering/Light | ポイントライトまたはディレクショナルライト。 |
ModelComponent |
Rendering/Model | インポートしたモデルを描画。サブメッシュごとのマテリアル差し替えに対応。 |
MeshComponent |
Rendering/Mesh | 単一のメッシュを描画。 |
UiDocumentComponent |
UI/UI Document | .ui ドキュメントを画面またはワールドに描画。ゲーム UI を参照。 |
UiRaycasterComponent |
UI/UI Raycaster | ワールド空間の UI ドキュメントをクリック可能にします。 |