上級チュートリアル: ゲームボードのナビゲーション

プロシージャルなゲームプレイが可能となり、キャラクターが環境内に現れ、リアルで没入感のある挙動で移動する高度なカスタムAR体験をビルドする。

このチュートリアルでは、 Gameboard を設定し、物理環境をスキャンして、ユーザー環境の内部理解を得る方法の例を紹介します。また、このコンポーネントのスマートな配置やナビゲーション機能をARアプリケーションに活用する方法についても詳しく説明します。

../../_images/GameboardScreenshot.png

シーンをセットアップする

現在 ゲームボード は環境を理解するためにメッシングをベースとしてビルドされています。開始するには、 メッシング: はじめに チュートリアルのステップに従ってください。

Unityエディターで繰り返し作業を行う場合は、 モックメッシュ を使用することをお勧めします。 MeshLoader プレハブをシーンに追加すると簡単に行うことができます。

以下のゲームボードのシーンやコードについては、 Assets/ARDKExamples/ContextAwareness/Gameboard ディレクトリ下の ARDK-examples を参照してください。

また、このサンプルシーンでは、グラフィカルユーザーインターフェイス(GUI)とタッチ入力で GameboardExampleManager スクリプトを使用して、エージェントの配置や移動を行うことができます。

レイヤー

ゲームボードは、シーン内の ARMeshManager コンポーネントによって生成されたUnityメッシュに対するレイキャスティングに依存しています。ARDK使用例パッケージを自分のプロジェクトにインポートしている場合は、次のように行う必要があります。

  1. プロジェクトに新しいレイヤー ARDK_Gameboard を追加します(Edit(編集) > Project Settings(プロジェクト設定) > Tags and Layers(タグとレイヤー) の順に移動)。

  2. レイヤー GameboardMeshChunk.prefabARDK_Gameboard に設定し、ARMeshManagerでメッシュプレハブとして使用するように設定されていることを確認します。

  3. GameboardManager スクリプトを探し、シーンのどこかに追加します。その Scan Settings(スキャン設定) -> Layer Mask(レイヤーマスク) の値を ARDK_Gameboard に設定します。

構成

GameboardManagerクラスは、ゲームボードを作成したり、スキャンのトリガーによってカメラの前で定期的に更新する上で役立ちます。ゲームボードの設定では、プレイ可能なエリアの定義方法や検出方法を変更できます。

  • TileSize : グリッド上のノードのメトリックサイズ。このサイズが小さいほど、グリッドの解像度は高くなります。高解像度のグリッドは、同じスキャン領域で実行されるレイキャストの数が多くなることを意味します。これにより、アプリケーションのパフォーマンスに影響を及ぼす可能性があります。

  • FlatFloorTolerance : セル内のノードのノイズを判断する際に使用する標準偏差の許容値を指します。この値の範囲外のセルはノイズが非常に多く、プレイ可能であるとみなされます。

  • MaxSlope : 推定される面は、多くの場合、完全に平面ではありません。この値は、隣接するノードを平面とみなすために許容される最大角度を度単位で定義します。

  • StepHeight : 2つのセルが同一平面上にあると見なすことができる最大標高差。

スキャン

その中でも特に重要なメソッドが Gameboard.Scan(origin, range) です。

スキャンすると、物理世界におけるゲームボードの内部解釈が更新されます。世界座標の原点を範囲付きで指定することで、アプリケーションに必要な世界の部分のみが更新されます。GameboardManagerスクリプトでは、スキャン間隔 ごとにカメラの前で新しいスキャンをトリガーして、ゲームボードを更新できます。GameboardManagerの UpdateGameboard 関数は次のようになります。

private Camera _camera;
float _scanRange;

private void UpdateGameboard()
{
    var cameraTransform = _camera.transform;
    var playerPosition = cameraTransform.position;
    var playerForward = cameraTransform.forward;

    // The origin of the scan should be in front of the player
    var origin = playerPosition + Vector3.ProjectOnPlane(playerForward, Vector3.up).normalized;

    // Scan the environment
    Gameboard.Scan(origin, range: _scanRange);
}

この方法では、融合されたメッシュを原点から重力に平行にレイキャストします。ボードの解像度によっては、この方法によってパフォーマンスに影響を及ぼす可能性があります。GameboardManagerは、デフォルトで1秒間に10回スキャンするように設定されています。

スマートな配置

Gameboard.RayCast メソッドを使うと、目的の位置が占有可能かどうかについてゲームボードにクエリを実行できます。この機能は、オブジェクトやゲームキャラクターを障害物(家具など)から離してスポーンするために使用されます。

using Niantic.ARDK.Extensions.Gameboard;

Camera _camera;
IGameboard _gameboard;
GameObject _object;

void HandlePlacement()
{
    // Get a ray pointing in the user's look direction
    var cameraTransform = _camera.transform;
    var ray = new Ray(cameraTransform.position, cameraTransform.forward);

    // Intersect the Gameboard with the ray
    if (_gameboard.RayCast(ray, out Vector3 hitPoint))
    {
        // Check whether the object can be fit in the resulting position
        if (_gameboard.CheckFit(center: hitPoint, 0.4f))
        {
            _object.transform.position = hitPoint;
        }
    }
}