This document is about: QUANTUM 2
SWITCH TO

マップベーキング

概要

Quantumでは、マップはUnity SceneとMapDataの2つの部分で構成されています。

Unity Sceneは、マップが読み込まれた時にロードされ、EntityViewsのようなマップの可視要素を含んでいます。これらのUnity GameObjectは、ゲーム内のエンティティをレンダリングする役割を担っています。

一方、MapDataには、決定論的シミュレーションがゲームプレイを推進するために使用するマップに関する情報が含まれています。

マップベーキング

デフォルトの設定では、Quantumはシーンが保存されるとき、編集モードを終了するとき(プレイモードに入る前)、またはアプリケーションを構築する前に、自動的にマップをベイクします。

プロジェクトの QuanutmEditorSettings アセットの Editor Features セクションで、シーン保存、プレイモード変更、アプリ構築のための自動マップベイクを有効または無効にすることができます。

自動マップベイクを無効にすることは一部の場面では便利かもしれませんが、手動マップベイクは時間がかかり、パイプラインにヒューマンエラーをもたらす可能性があり注意が必要です。そのため、ほとんどのプロジェクトでは、自動マップベイクを有効にしておくことが推奨されます。

quantumeditorsettings mapbaking
QuantumEditorSettings MapBaking

Quantumでシーンをベイクするためには、シーン内のGameObjectにMapDataコンポーネントが存在する必要があります。さらに、navmeshが存在する場合は、MapNavMeshUnityコンポーネントも必要です。Quantum SDK に付属する Game シーンには、必要な MapData のセットアップが既に用意されています。

MapDataのMonoBehaviourコンポーネントには、必要に応じてベイクプロセスを手動でトリガーするために使用できるボタンも含まれています。Bake All Modeは、ベイクプロセスの一部のステップをスキップするように調整することができます。

mapdata component
MapData コンポーネント

MapData

Quantum がマップをベイクすると、Resources/DB/Configsの下にあるMapDataアセットが生成されます。 ただし、必要に応じて、これらのアセットを別の場所に移動することができます。

マップを再ベイクすると MapData アセットに加えられた手動による変更が上書きされるため、MapData フィールドの値は通常手動で変更してはいけません。

MapData コンポーネントの User Asset フィールドを使用して、任意のアセットをマップに挿入し、シミュレーション側で取得できます。 これは、インスペクタでアセットを手動でリンクするか、カスタムマップベイクコールバックからアセットを割り当てることで実行できます。この例を以下に示します。

Quantum Editorの設定 BakeMapData

Quantumのマップベーキングコールバックは、MapDataのベーキングプロセスにカスタムステップを組み込むことができます。マップベーキングコールバックを実装するには、MapDataBakerCallbackから派生したクラスを作成します。以下はその実装例です:

C#

using Quantum;
using UnityEngine;

public class ExampleMapDataBaker : MapDataBakerCallback
{
    public override void OnBeforeBake(MapData data)
    {
    }

    public override void OnBake(MapData data)
    {
    }
}

Quantum の MapDataBakerCallback 属性は、複数のカスタムマップベーキングコールバックの実行順序を指定するために使用することができます。この属性を使用するには、カスタムマップベーキングコールバッククラスに追加して invokeOrder 値を指定します。値が小さいほど、マップベイク処理中にコールバックが早く実行されることになります。

以下はその例です:

C#

[MapDataBakerCallback(invokeOrder:5)]
public class ExampleMapDataBaker : MapDataBakerCallback

OnBeforeBakeは、他のMapDataのベイクが実行される前に呼び出されます。これにより、コンポーネントを追加したり削除したりして、Unityのシーンを調整することができます。

OnBake は、マップのすべての組み込みベイクステップが実行された後、MapAsset が Unity アセットに保存される前に呼び出されます。これにより、ベイクされたマップのすべてのデータにアクセスしながら、MapDataを調整することができます。

必要に応じてオーバーライドできる仮想コールバックが追加されています。OnBeforeBakeNavmesh, OnCollectNavMeshBakeData, OnCollectNavMeshes, OnBakeNavMesh また OnBeforeBake のオーバーロードでは、ベイクフラグとベイクのトリガーを提供しています。

マップにカスタムデータを追加する

コライダーやナブメッシュの他にも、ゲームマップにはゲームプレイに重要な要素が含まれていることがあります。不変的なデータを含める必要がある場合、マップ上のエンティティでそれを追加することは必須ではありません。そのような場合、MapData UnityコンポーネントのUser Assetフィールドを使用して、あらゆる形式のデータをシミュレーションに渡すことができます。これにより、オブジェクトの位置やゲームのルールなどをマップに含めることが可能になります。User Assetフィールドに割り当てられたデータは、シミュレーション内でアクセスし使用することができます。

例: スポーンポイント

マップをベイクする際にカスタムデータを利用する例として、ベイクしたマップにスポーンポイントを含めることができます。設計者は、このスポーンポイントをUnityシーンに配置し、自由に移動させることができます。

DSLファイル内にアセット宣言を追加します:

C#

asset MapCustomData;

次に、Quantumプロジェクトにスポーンポイントデータを格納するための新しいクラスを作成します:

C#

using System;
using Photon.Deterministic;
using Quantum.Core;
using Quantum.Inspector;

namespace Quantum {
    public unsafe partial class MapCustomData {
        [Serializable]
        public struct SpawnPointData {
            public FPVector3 Position;

            [Degrees]
            public FPQuaternion Rotation;
        }

        public SpawnPointData   DefaultSpawnPoint;
        public SpawnPointData[] SpawnPoints;

        public void SetEntityToSpawnPoint(Frame f, EntityRef entity, Int32? index) {
            var transform  = f.Unsafe.GetPointer<Transform3D>(entity);
            var spawnPoint = index.HasValue && index.Value < SpawnPoints.Length ? SpawnPoints[index.Value] : DefaultSpawnPoint;
            transform->Position = spawnPoint.Position;
            transform->Rotation = spawnPoint.Rotation;
        }
    }
}

Unityプロジェクトでアセットを利用できるようにするには、まずQuantumプロジェクトをビルドする必要があります。Quantumプロジェクトをビルドしたら、Unityプロジェクトに切り替えて、スポーンポイントの焼き付けを処理するクラスを新規に作成します:

C#


public class SpawnPointBaker : MapDataBakerCallback
{
    public override void OnBeforeBake(MapData data)
    {
    }

    public override void OnBake(MapData data)
    {
        var customData = UnityDB.FindAsset<MapCustomDataAsset>(data.Asset.Settings.UserAsset.Id);
        var spawnPoints = GameObject.FindGameObjectsWithTag("SpawnPoint");
        
        if (customData == null || spawnPoints.Length == 0)
        {
            return;
        }

        var defaultSpawnPoint = spawnPoints[0];
        if (customData.Settings.DefaultSpawnPoint.Equals(default(MapCustomData.SpawnPointData)))
        {
            customData.Settings.DefaultSpawnPoint.Position = defaultSpawnPoint.transform.position.ToFPVector3();
            customData.Settings.DefaultSpawnPoint.Rotation = defaultSpawnPoint.transform.rotation.ToFPQuaternion();
        }

        customData.Settings.SpawnPoints = new MapCustomData.SpawnPointData[spawnPoints.Length];
        for (var i = 0; i < spawnPoints.Length; i++)
        {
            customData.Settings.SpawnPoints[i].Position = spawnPoints[i].transform.position.ToFPVector3();
            customData.Settings.SpawnPoints[i].Rotation = spawnPoints[i].transform.rotation.ToFPQuaternion();
        }


#if UNITY_EDITOR
        EditorUtility.SetDirty(customData);
#endif
    }
}

このベイカーは比較的シンプルです。シーン内の SpawnPoint タグを持つすべての GameObject を集め、その位置と回転を抽出し、それをカスタムアセットに保存します。最後に、アセットにマーキングして、変更がディスクに保存されるようにします。

カスタムデータを使用するには、SpawnPointタグを持つGameObjectをシーンに追加します。そして、MapCustomDataAsset を作成し、マップの UserAsset フィールドに割り当てます。シミュレーションでスポーンポイントを利用するには、以下のコードを使います:

C#

var data = f.FindAsset<MapCustomData>(f.Map.UserAsset);
data.SetEntityToSpawnPoint(f, entity, spawnPointIndex);
Back to top