ソフトウェア開発ガイド
このガイドでは、Unity MARS を拡張する方法やアプリケーションに固有のカスタム動作を開発する方法について説明します。MARS のさまざまなサブシステムの仕組みを説明し、ニーズに合うように拡張するうえで役立つ例をいくつか紹介します。
パッケージのコンテンツ
Unity MARS パッケージは、以下のフォルダーで構成されています。
フォルダー | 説明 |
---|---|
Editor |
2D エディターの UI を追加または変更するための Unity エディタースクリプト集。 |
Interfaces |
Unity MARS の拡張機能を記述するために必要なインターフェーススクリプト集。 |
Runtime |
Unity MARS のコアランタイムシステム。 |
Tests |
単体テスト。 |
Unity MARS には、以下のパッケージ依存関係があります。
com.unity.xrtools.module-loader
com.unity.xrtools.utils
com.unity.textmeshpro
com.unity.timeline
com.unity.modules.physics
com.unity.modules.video
ソフトウェア開発者向けのトピック
このセクションでは、上級者向けのトピックについて説明します。デフォルトプロバイダーなど特殊なケースのために、ここで取り上げる Unity MARS の要素に直接アクセスする必要がある開発者を対象としています。
Generate all .csproj files
Unity.MARS
アセンブリを参照するコードを記述する際は、Preferences > External Tools にある Generate all .csproj files (すべての .csproj ファイルを生成する) オプションを有効にする必要があります。Unity MARS の Assets/MARS/Generated
には、アセンブリ定義参照を使用して Unity.MARS
アセンブリにコンパイルされた生成済みのコードが含まれています。Unity では、デフォルトではパッケージアセンブリの .csproj
ファイルは生成されませんが、Assets 内にアセンブリ定義参照の .asmref
があるため、Unity.MARS
のプロジェクトファイルが生成されます。残念ながら、このプロジェクトは MARS パッケージ内のコードを参照しないため、このアセンブリには大半の型がないように見えます。Generate all .csproj files オプションを有効にすると、メインの Unity.MARS
アセンブリのプロジェクトが生成され、MARS コードを操作する際には期待通りに機能します。
この設定は、現在のユーザーのすべての Unity プロジェクトに影響することに注意してください。
IDE 向けの統合パッケージ (Unity MARS を使用する場合は com.unity.ide.rider
など) を最新バージョンにアップデートすることをお勧めします。最新のバージョンでは、追加のプロジェクトファイルを生成するためのオプションがパッケージタイプごとに分類されています。これを使用する際は、Registry packages
が有効になっていることを確認してください。
MARS Session
MARS Session コンポーネントは、MARS シーン内でさまざまな用途で使用します。Unity MARS では基本的に、必要なトレイトのリストなどのシーンメタデータが MARS Session コンポーネント自体に格納され、実際のシーン内のエンティティに必要なトレイトに基づいてコンポーネントが自動的に設定されます。シーンに変更を加えると、MARS エディターの拡張機能によってシーンが分析され、MARS Session の要件リストに対してトレイトが追加または削除されます。このリストを直接編集することはできません。
MARS エディター拡張機能によって、MARS エンティティがアクティブなシーンに存在する場合は必ず MARS Session も存在して、メインカメラの親となるように処理されます。最初の MARS エンティティがシーンに追加されたときに、MARS Session が自動的に追加されます。
シーンにすでにカメラがある場合、カメラは MARS Session ゲームオブジェクトの子になり、MARSCamera スクリプトがカメラに追加されます。シーンにカメラがない場合は、MARS によって作成されます。MARS Session またはカメラを削除しようとしても、自動的に再作成されます。自動生成された MARS Session によって、カメラ位置のポーズを合成するユーザーゲームオブジェクトも追加されます。これにより、シーン内のクエリをユーザーに関連付けることができます。ユーザーゲームオブジェクトが必要ない場合は、安全に削除できます。
この動作を回避するには、Unity のメインメニューから Project Settings > MARS > Scene Tracking > Scene Module の順に移動し、Block Ensure Session オプションを有効にします。MARS によって、この設定がプロジェクトに保存されます。この設定は、ランタイムの "Session の存在を保証する" 動作にも影響します。このオプションは、public プロパティ MARSSceneModule.BlockEnsureSession
を介してスクリプトに公開されます。このオプションを一時的に有効にして、MARS を自動的に起動させずに、Session 階層に変更を加えたりランタイムにプロキシを作成したりできます。
MARS は、MARS の World Scale 機能をサポートするために、カメラゲームオブジェクトを MARS Session ゲームオブジェクトの子に設定します。MARS のシステムでは常にカメラには親があることを想定しています。この処理によって、ワールドスケールやカメラオフセットを取得/設定する必要がある場合に、コードの複雑さが緩和されます。
MARS Session コンポーネントのインスペクターで、シーンごとに Functionality Island (機能アイランド) のオーバーライドを設定できます。これを設定すると、グローバルなデフォルトの機能アイランドから設定された別のプロバイダーがシーンにあることになります。このフィールドは任意ですが、ほとんどの場合は空のままにする必要があります。
Module Loader
Module Loader パッケージ (com.unity.xrtools.module-loader
) を使用すると、複数のシステムが 1 つのプロジェクト内に共存し、相互作用できるようになります。これに依存するパッケージでは、IModule
またはバリアントを拡張するクラスが実装されます。これによって、指定可能な順序でエディター内やランタイムにロードおよびアンロードしたり、体系的で予測可能な方法で接続したりできるようになります。このパッケージには、Functionality Injection モジュールと Functional Injection (機能追加) 用の基本インターフェースが含まれています。このモジュールがあることで、各パッケージは互いを直接参照しなくても、機能を他のパッケージやユーザーコードに公開できます。
Module Loader には、以下の 2 つの方法でアクセスできます。
- Unity のメインメニューから Edit > Project Settings に移動し、Module Loader タブを選択する。
- プロジェクトで ModuleLoaderCore アセットを選択する。
ここで、Unity MARS の要素の有効と無効をトグルすることができます。トグルの中には、有効化された他のモジュールが依存しているために使用不可になっているものもあります。循環的な依存関係があるため、一度にすべての MARS 要素を無効にすることはできません。あるモジュールを無効にする際に、それに依存しているモジュールも無効にできます。相互に依存しているモジュールの詳細については、依存関係と依存モデルに関するドキュメントを参照してください。サンプルモジュールは、デフォルトで無効になっており、有効にすると問題が発生する可能性があります。Functionality Injection モジュールを無効にすることはできません。
Enabled Modules UI には、さまざまなモジュール順序が表示された一連の読み取り専用リストがあります。Load と Unload にはすべてのモジュールが含まれていますが、コールバックの順序は特定のインターフェースを実装するモジュールにのみ適用されます。
詳細については、Module Loader パッケージのドキュメント を参照してください。
モジュールの再ロード
Unity MARS システムの状態をリセットする必要がある場合は、Unity エディターを再起動する必要はありません。Reload Modules を使用して、MARS エディター拡張機能のみを再起動できます。これを行うには、Module Loader に移動し、Reload Modules をクリックします。
MARS データベース
Unity MARS は柔軟なデータベースレイヤーを基盤としています。このレイヤーは、ランタイムに構築され、MARS がネイティブにサポートするビルトインタイプと、プロバイダーやユーザースクリプトによって追加される新しいカスタムタイプで構成されます。
MARS データベースでは、世界に関する観測結果がデータに分解されます。データは、何らかの型の単一変数で構成され、データの文字列識別子であるトレイトで記述されます。データとトレイトは、受動的なものもあれば (平面に "壁" や "床" のラベルを付けるようなセマンティックタグ)、能動的なものもあります (例えば、顔のポーズは絶えず変化する値を持つ能動的なトレイトです)。
MARS データベースには、以下の 3 つのクラスがアクセスします
MARSBackend (読み取り)
このクラスは、一致するデータ (プロキシグループの場合はデータセット) を検索し、そのデータを要求したクラスや関数に返すクエリです。
Synthetic Object (書き込み)
合成オブジェクトと合成トレイトで構成される、ゲームオブジェクトに配置されるコンポーネント。このゲームオブジェクトがアクティブになると、MARS データベースにデータが書き戻されます。この仕組みを通じて、シミュレーション環境は現実の環境と同じように Unity MARS と相互作用します。
合成データを利用することで、さまざまな条件を、デザインしやすい単一のセマンティックなデータとしてまとめて作成できます。複製されたプロキシやプロキシグループ内の合成データは、本質的には視覚的に作成された Reasoning API です。また、合成データは、デジタル環境のスポーン点、ランドマーク点、辺の適切な位置や、橋をつなぐスペースなど、ユーザーが作成したコンテンツ内の重要な位置やデータをマークするためにも使用できます。これらのデータは、他のプロキシやプロキシグループで使用/予約できるため、さまざまな種類のコンテンツや環境がシンプルでフラットな階層で相互作用できます。
Reasoning API (読み取りと書き込み)
Reasoning API は、データベースの状態を調べて新しいセマンティックインターフェースや追加データを作成する、高度なスクリプトとシステムの集合体。詳細については、このページの Reasoning API のセクションを参照してください。
クエリ
クエリは、MARS データベース内のデータにアクセスするための手法です。ただし、開発者は、クエリを直接作成するのではなく、クエリを作成するためのオブジェクトを作成します。クエリは、一致が必要な条件と一致したデータが見つかったときのアクションで構成されます。
クエリには、条件以外にも、Common Query Data (共通クエリデータ) と Exclusivity (排他性) という 2 つの設定オプションがあります。
一般的なクエリデータ
以下のパラメーターは、MARS バックエンドがクエリを管理する方法に関するものです。通常のクエリとプロキシグループクエリで使用されます。
パラメーター | 定義 |
---|---|
Time Out | クエリが一致するデータを見つけるための試行を停止するまでの時間を指定します。 |
Update Match Interval | クエリの一致が更新されているかどうかを確認する頻度を指定します。 |
Reacquire on Loss | 条件に一致しなくなったときにクエリが別の一致を探すかどうかを指定します。 |
Exclusivity
このオプションは、すでに一致したデータを他のクエリで読み取れるようにするかどうかを制御します。Exclusivity を読み取り専用に設定し、すべてのデータに対して一致を許可しつつアプリケーションの視覚的なフローには干渉しないようにすることもできます。例えば、テーブルの外観をした 2 つのプロキシがある場合、アプリケーションが 1 つ目のプロキシを検出して、その上にコンテンツを配置し、2 つ目のプロキシは無視するように設定できます。
プロキシグループクエリ
"クエリ" という用語は、通常、1 つのプロキシ (1 つのテーブルや 1 つのフロア平面など) のデータのコレクションに対するクエリを指します。プロキシグループクエリは、各プロキシ間で一致しなければならない一連の関係を伴う複数の通常クエリを指します。
必須の子プロキシ
プロキシグループ内の各子プロキシが必須か必須でないかを設定します。プロキシグループが最初に一致する際は、必須かどうかにかかわらず、すべての子プロキシが一致する必要があります。必須の子プロキシの条件か、その子プロキシが含まれる関係が一致しなくなると、プロキシグループ全体が一致しなくなります。一方で、必須でない子プロキシがなくなった場合、プロキシグループは他の子プロキシの一致するデータを引き続き使用します。
条件の記述
プロキシの Condition コンポーネントで、MARS データベース内のデータとの一致を調べるトレイトを (オプションで、値の範囲も) 定義します。Unity MARS には、一般的なユースケース向けに条件が記述されたスクリプトが多数含まれているほか、開発者が自分で作成するための API も用意されています。
条件は、データベースでトレイト名でフィルタリングされた 1 種類のデータに対して適用されます。
条件を記述するには、以下の手順に従います。
以下のテンプレートを使用して新しいスクリプトを作成します。
public class _ConditionName_Condition : Condition<_dataType_> { static readonly TraitRequirement[] k_RequiredTraits = { _TraitDefinition_ }; public override TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; } public override float RateDataMatch(ref _dataType_ data) }
k_RequiredTraits
フィールドとRateDataMatch()
メソッドを設定します。k_RequiredTraits
配列にはTraitRequirement
を 1 つだけ含める必要があります。これは、この条件が適用されるトレイトの定義となります。RateDataMatch()
メソッドは、指定されたデータ型の要素を 1 つ受け取り、それが条件にどの程度一致するかを 0-1 の数値で返します (0 は不一致、1 は完全一致)。これは、MARS データベース内のエントリーを一度に 1 つ照会することを意味しています。
条件は一度に 1 つのトレイトと設定にのみ適用されますが、1 つのオブジェクトに複数の条件を持たせることができます。このワークフローが推奨です。条件を一度に複数のデータに適用する必要がある場合は、MultiConditions を使用してください。
MultiConditions の記述
プロキシの MultiCondition コンポーネントでは、MARS データベース内のデータとの一致を調べる複数のトレイトを定義します。Unity MARS には、一般的なユースケース向けに条件が記述されたスクリプトがいくつか含まれているほか、開発者が自分で作成するための API も用意されています。
MultiCondition を記述するには、以下の手順に従います。
以下のテンプレートを使用して新しいスクリプトを作成します。
public class _MultiConditionName_Condition : MultiCondition<_conditionType1_,_conditionType2_> { [System.Serializable] public class _conditionType1_ : SubCondition, ICondition<_dataType_> { static readonly TraitRequirement[] k_RequiredTraits = { _TraitDefinition_ }; public string traitName { get { return k_RequiredTraits[0].TraitName; } } public TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; } public float RateDataMatch(ref _dataType_ data) { } } [System.Serializable] public class _conditionType2_ : SubCondition, ICondition<_dataType_> { static readonly TraitRequirement[] k_RequiredTraits = { _TraitDefinition_ }; public string traitName { get { return k_RequiredTraits[0].TraitName; } } public TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; } public float RateDataMatch(ref _dataType_ data) { } } }
各 SubCondition の
k_RequiredTraits
フィールドとRateDataMatch()
メソッドを設定します。SubCondition に OnValidate メソッドが必要な場合は、外部クラスでそれぞれに実装する必要があります。
関係の記述
プロキシグループの Relation コンポーネントでは、MARS データベース内のデータとの一致を調べるトレイトを (オプションで、値の範囲も) 定義します。Unity MARS には、一般的なユースケース向けに条件が記述されたスクリプトが多数含まれているほか、開発者が自分で作成するための API も用意されています。
関係を記述するには、以下の手順に従います。
以下のテンプレートを使用して新しいスクリプトを作成します。
public class _RelationName_Relation : Relation<_dataType_> { static readonly TraitRequirement[] k_RequiredTraits = { _child1TraitDefinition_, _child2TraitDefinition_ }; public override TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; } public override float RateDataMatch(ref _dataType_ child1Data, ref _dataType_ child2Data) { } }
k_RequiredTraits
フィールドとRateDataMatch()
メソッドを設定します。k_RequiredTraits
配列はTraitRequirement
を 2 つ含む必要があります。1 つ目のエントリーは 1 つ目の子に使用されるトレイトの定義、2 つ目のエントリーは 2 つ目の子に使用されるトレイトの定義を設定します。RateDataMatch
メソッドは、指定されたデータ型の 2 つの要素を受け取ります。これは、MARS データベース内のコンテキストのペアが同時に照会されることを意味しています。一般に、関係では一度に 1 つのプロパティと設定しか確認されません。
MultiRelations の記述
プロキシグループの MultiRelation コンポーネントでは、グループ内の 2 つのプロキシ間の複数の関係を定義します。関係ごとに一致の有無が照会されます。Unity MARS には、サンプルとしてスクリプトが 1 つ含まれているほか、開発者が自分で作成するための API も用意されています。
MultiRelation を記述するには、以下の手順に従います。
以下のテンプレートを使用して新しいスクリプトを作成します。
public class _MultiRelationName_ : MultiRelation<_relationType1_,_relationType2_> { [System.Serializable] public class _relationType1_ : SubRelation, IRelation<_dataType_> { static readonly TraitRequirement[] k_RequiredTraits = { _child1TraitDefinition_, _child2TraitDefinition_ }; public string child1TraitName { get { return k_RequiredTraits[0].TraitName; } } public string child2TraitName { get { return k_RequiredTraits[1].TraitName; } } public TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; } public float RateDataMatch(ref _dataType_ child1Data, ref _dataType_ child2Data) { } } [System.Serializable] public class _relationType2_ : SubRelation, IRelation<_dataType_> { static readonly TraitRequirement[] k_RequiredTraits = { _child1TraitDefinition_, _child2TraitDefinition_ }; public string child1TraitName { get { return k_RequiredTraits[0].TraitName; } } public string child2TraitName { get { return k_RequiredTraits[1].TraitName; } } public TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; } public float RateDataMatch(ref _dataType_ child1Data, ref _dataType_ child2Data) { } } }
各 SubRelation の
k_RequiredTraits
フィールドとRateDataMatch()
メソッドを設定します。SubRelation に OnValidate メソッドが必要な場合は、外部クラスでそれぞれに実装する必要があります。
アクションの記述
アクションは、データベース内の変更を AR のライフサイクルイベントとして Unity シーン内の変更に変換するためのものです。Action コンポーネントを作成するには、アクションまたはプロキシグループアクションのインターフェースを実装するコードを記述します。プロキシには Action コンポーネントを、プロキシグループには ProxyGroup Action コンポーネントを適用することができます。
適用できる AR ライフサイクルイベントは、以下のとおりです。
- Acquire (取得): 一致する現実世界のデータが最初に見つかって適用されるときに発動されます。
- Update (更新): 一致した現実世界データが変更された場合に指定された間隔で発動されます。
- Timeout (タイムアウト): 一連の条件が所定の時間内に見つからなかった場合に発動されます。
- Loss (喪失): 一致した現実世界データが大きく変化し、所定の条件を満たさなくなった場合に発動されます。
アクションを記述するには、以下の手順に従います。
以下のテンプレートを使用して新しいスクリプトを作成します。
public class _ActionName_Action : MonoBehaviour, IMatchAcquireHandler, IMatchUpdateHandler, IMatchLossHandler, IMatchTimeoutHandler, IRequiresTraits { static readonly TraitRequirement[] k_RequiredTraits; public void OnMatchAcquire(QueryResult queryResult) {} public void OnMatchUpdate(QueryResult queryResult) {} public void OnMatchLoss(QueryResult queryResult) {} public void OnMatchTimeout(QueryArgs queryArgs) {} public TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; } }
反応 (Acquire、Update、Timeout、Loss) したい AR ライフサイクルイベントごとに、該当するインターフェースを追加し、対応する関数を設定します。
QueryResult には、少なくともオブジェクトの条件に必要なデータを含めます。それ以外のデータを含めて、そのデータが存在するかどうかを確認することもできます。一致するオプションに対して特定のアクションを必ず発生させるか任意であるかを選択できます。
k_RequiredTraits
には、このアクションを発動させるトレイトをすべて含めます。例については、SetAlignedPoseAction
クラスを参照してください。トレイトの詳細やトレイトを必須にする方法については、トレイトに関するドキュメントを参照してください。
MARSEntity インスペクターにクラスを設定する
作成した新しいアクションと条件は、MARS Entity インスペクター UI の Add MARS Component > Action/Condition > Other に、自動的に積み重ねた形式で表示されます。カスタムのメニューパスを指定することもできます。これを行うには、以下のようにクラスに MonoBehaviorComponentMenu
属性を追加します。
[MonoBehaviourComponentMenu(typeof(_YourAction_), "Action/_YourActionPath_")]
合成データ
MARS プロキシを参照する際は、条件を使用して、必要なデータのリストを作成します。Synthetic Data (合成データ) システムは、これをミラーリングします。ゲームオブジェクトや従来のコンテンツが Synthetic のコンポーネントで装飾され、合成コンポーネントによってプロパティが収集されて MARS データベースに追加されます。合成データは、Reasoning API のようなさまざまなアクティビティの外観インターフェースとしても機能します。世界を装飾する高度なワークフローのほとんどが、このシステムに依存しています。
合成データを使用するには、以下の手順に従います。
MARS データベースにミラーリングするゲームオブジェクトを作成または指定します。既存の AR データをよりセマンティックな情報で装飾する場合は、プロキシゲームオブジェクトの子ゲームオブジェクトを使用できます。また、シミュレーションデータを操作する場合は、ルートレベルのゲームオブジェクトを使用できます。
"SynthesizedObject" コンポーネントを追加します。
任意の数の Synthesized Traits コンポーネントまたは Synthesized Data コンポーネントを追加します。それぞれ、ゲームオブジェクトの異なる要素を MARS データベースにミラーリングします。
Synthesized Object (合成されたオブジェクト) が有効化/無効化されると、ランタイムまたはシミュレーション時にルートレベルで、合成されたオブジェクトが追加/削除されます。MARSEntity の子である合成されたオブジェクトは、親が取得 (Acquire) /喪失 (Loss) されたときにデータベースに追加/削除されます。
- 位置に基づくトレイトなど、特定のトレイトは、SynthesizedObject のトランスフォームが変化すると、値を更新します。Update AR ライフサイクルメソッドでも、SynthesizedObject の値の更新が発動されます。
SynthesizedTrait の記述
SynthesizedTrait を記述するには、以下の手順に従います。
以下のテンプレートを使用してスクリプトを作成します。
public class Synthesized_TraitName_ : SynthesizedTrait<_DataType_> { public override string TraitName { get; } public override bool UpdateWithTransform { get; } public override _DataType _GetTraitData() }
上記のメソッドを設定します。
目的の SynthesizedObject にメソッドを追加します。他に SynthesizedTrait があれば、それも同様に行います。
同じトレイトタイプを使用する Condition または Relation が少なくとも 1 つ定義されている必要があります。これらが定義されていない場合、そのトレイトタイプのデータベースコードは生成されません。
Reasoning API
Unity MARS は、AR シーンを豊かに装飾するというコンセプトがベースにあります。例えば、シーンには、"床" とラベル付けされた平面、"家具" とラベル付けされてライト値が添付されたバウンディングボリューム、その他ラベル付けされたさまざまな要素で構成されます。現在、ほとんどのプロバイダーは、平面や顔など一度に 1 種類のデータしか提供しておらず、このような豊富なデータは提供されていません。
Reasoning API は、AR ハードウェア/ソフトウェアスタックをフルに活用して、このギャップを埋めます。そのために、MARS データベースのデータを作成したり変更したりします。データベース内の複数のデータを一度に認識することができ、異なるデータセットを相互に関連付けたり、既存のデータに基づいて足りない部分を推論したりすることができます。
パッケージには、床面にラベルを付ける Reasoning API のサンプルが付属しています。このサンプルを使用すると、スマートフォンベースの AR を実現する強力な機能を活用できます。
Reasoning API の選択基準
Reasoning API は、以下の基準に基づいて選択、実行されます。
Reasoning API が実行する必要のあるデータは存在するか? 例えば、Floor Reasoning API では、平面がデータベース内に事前に存在している必要があるため、その有無を調べて、どの平面が床平面に関連している可能性が高いかを推測します。
アプリケーションは Reasoning API が提供するデータを必要としているか? 例えば、Unity MARS で設計されたアプリケーションが、平面トレイトを必要とする条件を使用しない場合、Floor Reasoning API は実行される理由がないため (実行可能であっても) 実行されません。
この Reasoning API が提供するデータは、別のソースからのものか? 例えば、セマンティックなラベルが設定された平面を提供する AR ハードウェアで MARS アプリケーションを実行するとします。これらはすでに "床" ラベルが設定されてデータベースに追加されています。この場合、Floor Reasoning API は、新しい要素を追加できないため、実行されません。
Reasoning API の記述
Reasoning API は、以下のテンプレートをたたき台に使用してスクリプトを作成します。
[CreateAssetMenu(menuName = “Mars/_Name_ ReasoningAPI”)]
public class _Name_ReasoningAPI : ScriptableObject, IReasoningAPI
{
static readonly TraitDefinition[] k_ProvidedTraits;
static readonly TraitRequirement[] k_RequiredTraits;
public float processSceneInterval { get; }
public TraitDefinition[] GetProvidedTraits() { return k_ProvidedTraits; }
public TraitRequirement[] GetRequiredTraits() { return k_RequiredTraits; }
public void Setup()
public void TearDown()
public void ProcessScene()
public void UpdateData()
}
このテンプレートは、以下のパーツで構成されています。
k_ProvidedTraits
: この Reasoning API がアクティブな MARS シーンに追加するトレイトの配列です。k_RequiredTraits
: Reasoning API を実行するためにデータベースに存在する必要のあるトレイトの配列です。Setup()
: データベースとそのコンテンツへの参照を取得するための 1 回限りの設定を実行します。TearDown()
:Setup()
メソッドで設定されたリソースを解放します。ProcessScene()
: リソースを大量に消費する処理のために、(フレーム単位ではなく) 頻繁に呼び出されるメソッドです。UpdateData()
: Reasoning API によって作成または変更されたデータを常にシーンに反映されるようにするために呼び出される、フレーム単位のメソッドです。
Reasoning API を作成できたら、使い始めるために以下の手順を実行します。
Reasoning API にデータを追加します。これを行うには、
IProvidesTraits<T>
、IRequiresTraits<T>
、またはIUsesMARSData<T>
インターフェースを追加します。これらを追加することで、MARS データベースのデータにアクセスして、データベースエントリーのデータを追加、編集、および削除することもできるようになります。IUsesMARSData
によって提供されるGetCollection<T>
メソッドは、特定のタイプのデータベース内のすべてのデータを取得する場合に特に役立ちます。プロジェクトに Reasoning API のインスタンスを作成します。Project ウィンドウで右クリックし、Create > MARS > Name Reasoning API を選択します。
プロジェクトで ReasoningModule ゲームオブジェクトを見つけて、Reasoning APIs セクションを展開します。
この配列に Reasoning API を追加します。
シミュレーションと互換性のある動作の記述
Unity MARS 内のシミュレーションは、アクティブなシーン内のすべてのゲームオブジェクトを Simulation View にコピーし、コピーされた MonoBehaviour
(ISimulatable
インターフェースを実装している) に runInEditMode
プロパティを設定します。
シミュレーションで実行されるカスタムの動作を作成する際は、以下の点に注意してください。
- 作成する動作は、シミュレーションの間に
MonoBehaviour
コールバックを受け取れるようにISimulatable
を実装する必要があります。 - 作成する動作によってゲームオブジェクトをインスタンス化する場合は、
GameObjectUtils.Create
またはGameObjectUtils.Instantiate
を使用してください。これらのユーティリティは、それぞれ、GameObject
コンストラクター用とObject.Instantiate
用のラッパーです。シミュレーション中に呼び出されると、インスタンス化されたゲームオブジェクトが Simulation View に追加され、そのISimulatable
動作が編集モードで実行されます。 - 作成する動作によってゲームオブジェクトを除去する場合は、
UnityObjectUtils.Destroy
を使用してください。このユーティリティは、再生モードで呼び出されるとObject.Destroy
を呼び出し、編集モードで呼び出されるとObject.DestroyImmediate
を呼び出します。 - 状況によっては、シミュレーションされたゲームオブジェクトがシミュレーション間で (除去されたり新しいコピーに置き換えられたりせずに) 維持されることがあります。このようなときは、カスタムの
ISimulatable
動作によってそのゲームオブジェクトや別のゲームオブジェクトの状態が変化した場合にその状態がリセットされるように、OnDisable
を設定してください。また、シミュレーションが開始されたときに必要な設定が動作によって実行される必要がある場合は、OnEnable
を設定してください。Awake
は、動作のrunInEditMode
が初めてtrue
に設定されたときにだけ呼び出されます。
MARS の時間
MarsTime.Time
は、Unity MARS のライフサイクルが開始されて (アクティブな MARS Session が OnEnable
を受け取ったとき) から経過した時間です。一定の間隔 (MarsTime.TimeStep
) で時間を刻み、各間隔の後に、MarsTime.MarsUpdate
コールバックが発動されます。
MarsTime.TimeScale
は、MarsTime.Time
に影響しますが、MarsTime.TimeStep
には影響しません。つまり、実質的には、MarsTime.TimeScale
が増えると、プレイヤーループの更新あたりの MarsUpdate
の数が増加することになります。
シミュレーションは、さまざまなタイムスケールで実行できるため、MARS のコアシステムとシミュレーションデータプロバイダーは、MarsTime
プロパティと MarsUpdate
コールバックを使用して、動作が確定的になるようにする必要があります。シミュレーション可能なカスタム動作の中には、タイムスケールにかかわらず確定的に動作することが重要になるものもあります。
このようなカスタム動作では、MARS Time API を使用し、以下のガイドラインに従ってください。
MonoBehaviour.Update
の代わりにMarsTime.MarsUpdate
を使用するTime.time
の代わりにMarsTime.Time
を使用するTime.deltaTime
の代わりにMarsTime.TimeStep
を使用するTime.frameCount
の代わりにMarsTime.FrameCount
を使用するTime.timeScale
の代わりにMarsTime.TimeScale
を使用する
作成する動作で MonoBehaviour.Update
を使用しつつ、タイムスケールが設定されたシミュレーションとの互換性を維持したい場合は、以下のガイドラインに従って、MarsTime.TimeScale
を時間ベースの計算の考慮に入れてください。
Time.time
の代わりにMarsTime.Time
を使用するTime.deltaTime
の代わりにMarsTime.ScaledDeltaTime
を使用する
カメラの検出
ISimulatable
でカメラを取得する場合は、シーンカメラへの直接参照をシリアル化する必要がない限り、MarsRuntimeUtils.GetActiveCamera()
を使用してください。該当するシナリオでは、以下のメソッドを使用してください。
GetActiveCamera()
は、シミュレーション時はシミュレーションからアクティブなカメラを取得し、再生モードのときは MARS Session カメラを取得します。MarsRuntimeUtils.GetSessionAssociatedCamera()
は、アクティブな (MARSSession.Instance
) MARSSession カメラを返します。
どちらのメソッドも、Camera.main
にフォールバックするか、それも null の場合は任意のカメラを検出するオプションがあります。
MARS エディターシステム
Data Visual
Data Visual は、シミュレーションで非表示のレプリケーターによって作成されるプロキシです。このオブジェクトは、Create Tool や Compare Tool などのエディターツールで使用されます。
Content Scene Hierarchy パネルに Data Visual を表示するには、Project Settings > MARS > Editor Visuals > Simulation Data Visuals で Show Data Visuals In Hierarchy オプションを有効にします。
Project Settings で、Disable Simulation Data Visuals にトグルして、シミュレーションが開始されるときに Data Visual が生成されないようにすることもできます。Data Visual が無効になると、それを使用するツールは機能しなくなりますので、注意してください。