This document is about: QUANTUM 1
SWITCH TO

Migration Notes

まずリリース履歴を読んでから、各SDKパッケージ内のアップグレードインストラクションを確認してください。このリソースはリファレンスとして使用し、変更に関する詳細な情報を取得するようにしてください。

一度に移行するのは1バージョンのみにして、必ず結果を確認してから次に進むようにします。

目次

1.2.3から1.2.4へ移行

フィルター

DSLで使用できる複合キーワードが3つあります。「has」、「not」、「any」です。以下にサンプルとイテレーションの結果を簡単に示しました。

filter MyEntities {
  has Transform3D;
  has DynamicBody3D;
  not Prefab;
  any {
    PoisonArea;
    EnemyTrigger;
  }
}
  • "has" 選択したコンポーネントすべてを含むエンティティをフィルタして抽出します;
  • "not" 選択したコンポーネントのうちどれか一つでも含むエンティティをフィルタしてはじきます;
  • "any" 選択したコンポーネントのうち1つのみを含むエンティティだけをフィルタして抽出します

すべてのフィルターイテレータアクセサはFrame.Filtersオブジェクト内でグループ 化されます(上記の場合はFrame.Filters.MyEntities)。イテレータアイテム (Current)は、「has」「any」キーワードで定義されたすべてのコンポーネントに対 してキャッシュポインタを含みます(期待される意味に従ってnullになるものもあり ます)。

Unityのnavmesheをすべて再インポートして再度navmesheをすべてベイクしてください。

DBフォルダー内にある古いQuantum navmeshアセットはすべてシリアライゼーションエラーでゲームのクラッシュにつながります。

インポートタブとアルゴリズムは更新され速度と堅牢さが増します。MapNavMeshDefinitionインスペクターの新しい設定のデフォルトの構成からはじめるのがいいでしょう。詳細はこちらを参照してください。ナビゲーションシステム - Creating A Quantum Navmesh

NavMeshクラスのメソッドのシグネチャに INavMeshRegionMask という新しいパラメータがあります。切り替え可能なnavmeshリージョンで必要なものです。Frameクラスに実装されます。以下を参照してください。

C#

// たとえば、LineOfSightメソッドの使用
public bool LineOfSight(FPVector2 p0, FPVector2 p1, INavMeshRegionMask regionMask);

public override void Update(Frame frame) {
    var navmesh = frame.Map.NavMeshes["NavMeshUnity"];
    navmesh.LineOfSight(FPVector2.Zero, FPVector2.One, frame);
}

SimulationConfig.ProximityFactorSimulationConfig.AvoidanceRangeに置き換えられました。ファクターがエージェントの領域で増加し、2つのエージェント間の距離を測れるようになりました。新しい領域値が示すのは2つのエージェント間の距離から、それぞれのエージェントの半径を引いたものです。

new AvoidanceRange ~= AgentConfig.Range * (old ProximityFactor - 2)

navmeshエージェントAPIはアップグレードされました。特筆すべき変更は以下の通りです。

  • NavMeshAgent.SetTarget() は入力位置を「Target」および「InternalTarget」としての潜在的な補正位置として設定します。
  • NavMeshAgent.AgentConfig = configの代わりにNavMeshAgent.Init(NavMeshAgentConfig agentConfig)を使用してエージェントを初期化します。内部を初期化するにはさらなる労力を必要とします。
  • エージェントの半径が各navmeshで保存されたMinAgentRadiusと連動して動作するようになりました。エージェントのウェイポイントは境界線から離れてagent radius - MinAgentRadiusユニットを設定します。言い換えると、Unity NavMeshの生成に使用されるるMinAgentRadiusは最小のユニットの半径になるということです。
  • Epsilonは減少し、最終的なターゲットに到達するためだけに使用されます。0.01に設定するようにしてください。
  • PathQualityGoodに設定します。違う設定にするとファンネリングの経験則が変わってしまいます。この設定は計算間のもので、よりよい最終パスのためです。
  • BreakingOnWaypointはデフォルトではオフになりました。

すべてのオプションについての情報はこちら: Navigation - NavMeshAgent API

現在はデフォルトで無効になっています。 SimulationConfig.NavMeshAgent.EnabledCallbacksで切り替えてアクティブ化します。

これを(ナビゲーション)マルチスレッド最適化と組み合わせて使用する場合は注意してください。 コールバック中はエンティティへのアクセスのみが許可されます!!!

マップベーキング(重大な変更)

マップしたすべての静的コライダーをすべてベイクします。

3D物理のベイクを変更しました。再ベイクすると、3Dコライダーをまったく使用しなくても、すべてが正しく初期化されるようになります。

エンティティプレハブビュー・アップデーター

EntityPrefabViewUpdater.csの修正バージョンがある場合、またはそれから派生している場合は、新しいバージョンからやり直して、修正を削除することを検討してください。 なぜそうするべきかの詳細については、こちらをお読みください: What’s New In 1.2.4 - New Entity Interpolator

EntityPrefabRoot.InterpolatePositionSpeedEntityPrefabRoot.InterpolateRotationSpeedは削除されました。 コードでそれらを使用し、アセットに変数を保存する場合は、UnityプロジェクトをアップグレードするときにそれらをEntityPrefabRootスクリプトに追加し直します。

C#

public unsafe class EntityPrefabRoot : MonoBehaviour {
  public float InterpolatePositionSpeed;
  public float InterpolateRotationSpeed;
  // ..
}

その他

    • QuantumGameCallbacks.InputConfirmedDelegateのシグネチャが変更され、パラメータクラスを削除して入力を記録するときにアロケーションを削減します。

C#

QuantumGameCallbacks.InputConfirmedDelegate(QuantumGame game, Int32 frame, Int32 player, Byte[] rpc, Byte[] data, DeterministicInputFlags flags)
  • クラウドのQuantumプラグインには「QuantumPlugin」という名前が付けられており、次の例のようにPhoton RoomOptionsに名前を追加する必要があります。

charp

RoomOptions roomOptions = new RoomOptions();
// This line is new:
roomOptions.Plugins = new string[] { "QuantumPlugin" };
PhotonNetwork.CreateRoom(null, roomOptions, null);

1.2.2から1.2.3へ移行

DSL: プリミティブ型配列生成を変更しました(互換性を破る変更)

以下のようにqtnファイルの配列を定義します。

component Foo {
    array<Int32>[26] Parameters;
}

// before: access via method
public Int32* Parameters(Int32 index)

// now: access via indices
public fixed Int32 Parameters[26];

コード内で定義した配列を使用する場所を修正します。以下を参照してください。

C#

// 古い方法
*entity->Foo.Parameters(i) = 0;

// 新しい方法
entity->Foo.Parameters[i] = 0;

indexing movable fixed buffers' is not available in C# 7.0というエラーが生じて構文を変換できない場合は、7.3以上の言語を使用してください。
生成したコンポーネントの新しい部分構造体を作成し以下のgetメソッドを追加します。以下を参照してください。

C#

// `<NAME>`を配列フィールド名に、 `<TYPE>`を配列の汎用型に置き換えます。
public unsafe partial struct Foo {
    public <TYPE>* <NAME>Getter(Int32 index) {
        if (index < 0 || index >= <NAME>Size) { Quantum.Core.ILHelper.ArrayOutOfRange(); }
        fixed (<TYPE>* p = <NAME>) { return &p[index]; }
    }
}

2.5Dもしくは2D垂直機能の有効化が必要です (互換性を破る変更)

2.5Dを使用している場合(物理オブジェクトにおける高さなど)は SimulationConfig.UseVerticalTransform有効化 が必要です。

DynamicScene.OverlapShape()がContact Normalを生成するようになりました。

返されたヒットオブジェクトのDynamicHit.Normalフィールドは正しく入力されるようになりました。

これはデフォルトで有効化されています。計算時間の節約のためCore.DynamicScene.OverlapOptions.SkipNormalを受け渡して無効化することも可能です。

C#

using (var hits = f.Scene.OverlapShape(position, rotation, shape), -1, Core.DynamicScene.OverlapOptions.SkipNormal)) { }

PUNバージョン1.92

このバージョンでは、UnityプロジェクトのPhoton Unity Networking (PUN)フォルダ内のファイルがアップデートされました。Quantum SDKアップグレードのUnityパッケージ内にファイルがあります。このPUNアップグレードには、Unity2018のコンパイル修正も含まれていますが、それに関してはUnityの最新版を使用している場合、既に追加されている可能性もあります。
Quantumが使用しているPUNバージョンは、アセットストアの Photon Unity Networking Classic とほぼ同じです。

1.2.1から1.2.2へ移行

SimulationConfigアセット (互換性を破る変更)

背景情報

DefaultPhysicsMaterialDefaultNavMeshAgentConfig と並んで、SimulationConfigAsset は、QuantumGameとDBに受け渡されるため多くのボイラープレートコードを必要としていましたが、これら3つは全てDBの一部となりました。

これにより、4つのポイントが簡単になります。1)Unityリソースからシミュレーションへの受け渡し 2)シーンのリロード後、壊れた物理マテリアルのバグの修正 3)自動的に処理され、個別に保存する必要がなくなりました。 4)カスタムサーバープラグインでシミュレーションを実行するのにリプレイファイルは必要ありません。

リプレイを追加する前にリファクタリングが必要でしたが、簡単に移行できるようになりました。次のセクションで説明します。

移行

  1. SimulationConfig上の現在のDefaultPhysicsMaterialデータとDefaultNavMeshAgentデータは 失われます。 移行 前に、必ずこれらのスクリーンショットを作成してください(その際、NavMeshAgentとPhysicsMaterialの詳細を展開してください)。
  2. Unityエディター を使って SimulationConfig.assetAssets/Quantum/Resources からDBフォルダ Assets/Resources/DB/Configsへ移動します。/Configsについては任意です。SimulationConfig.assetファイルがDBファイル内にあるということが大切です。
  3. Unityアセットファクトリを用いて(右クリック)新しいアセットを2つ作成します。Quantum/Assets/Physics/PhysicsMaterialおよびQuantum/Assets/Physics/NavMeshAgentConfigを作成しそれぞれ名前を付けます。(例:DefaultPhysicsMaterial、 DefaultNavMeshAgentConfig)
Simulation Config Project
  1. PhysicsMaterial GUIDを$DEFAULT_PHYSICS_MATERIALに設定します。
Simulation Config Material Name
  1. NavMeshAgentConfig GUIDを$DEFAULT_NAVMESH_AGENTに設定します。
  2. ステップ1で保存したデータを入力します。
  3. PhysicsMaterialアセットおよびNavMeshAgentConfigアセットをSimulationConfigの適切なスロットにドラッグアンドドロップします。
Simulation Config Drag And Drop
  1. SimulationConfigアセットに guid があることを確認してください。
  2. UnityDB.Init() および QuantumRunner.StartParameter は、引数としてSimulationConfigをリクエストしなくなりました。

RuntimeConfig にドラッグアンドドロップフィールドのSimulationConfigアセットができました。これにより、それぞれのゲームセッションに個別のSimulationConfigsを持てるようになりました。フィールドに入力しない場合は、DBの一番上にあるものが使用されます。

Simulation Config Quantum Runner

以下のようなQuantumのシミュレーションコード内のシミュレーション設定にアクセスします。

C#

public unsafe class MySystem : SystemBase {
    public override void OnInit(Frame f) {
        f.RuntimeConfig.SimulationConfig.Instance...
    }
}

QuantumGameリファクタリング (互換性を破る変更)

移行

  • 互換性を破る変更: QuantumGameクラスをquantum.systemsに移動しました。詳細については1.2.2の追加機能を参照の上、SDKのupgrade/upgrade_instructions.txtファイルに従ってファイルを追加したり削除したりしてください。
  • 互換性を破る変更: QuantumGameから古いプロパティを削除しました。以下を参照してください。
    * 例: QuantumGame.Frame、QuantumGame.Running,、QuantumGame.IsLocalPlayer、 QuantumGame.RuntimeConfigなど
  • 互換性を破る変更: QUANTUM_FLIP_EVENT_ORDER 定義を使用している場合は、quantum.systems.csprojにこの定義をコピーする必要があります。
  • QuantumGame.Instance は、古いとマークされていますが、今の時点ではまだ動作します。
    • シングルトンの代わりにコールバックとイベント内で引数QuantumGame/IDeterministicGameを使用します。
    • Start()内もしくはUpdate()メソッドでQuantumGame.Instance != nullをチェックするかわりにOnGameStartに登録します。警告:Unityスクリプトでは問題なく作動しますが、それはOnGameStartが呼び出された後、ゲームオブジェクトがシーンの再読み込み(AutoLoadSceneFromMap)で壊れていない場合のみです。
    • もしくは、QuantumGame.InstanceQuantumRunner.Default.Gameと交換します。
    • 警告: QuantumInstantReplay.cs内のQuantumGame.Instance = _liveGame;行は変更したり交換したりしないでください。後方互換性のために保存しておく必要があります。
  • QuantumRunner.Current も、古いとマークされています。
    • セッションを取得するためにこれを使用していた場合は、QuantumGameからもセッションを取得できます。
    • もしくは、QuantumRunner.CurrentをQuantumRunner.Defaultと交換します。
  • UILeaveGame.OnLeaveRoutine()は変更されました。ゲーム内で再度これを使用する場合は、最新のコードであることをご確認ください。
    • QuantumRunner.ShutdownAll() は、少なくとも1つのアクティブなランナーがクローズされた場合にtrueを返します。インスタントリプレイなどの同時セッションのクローズも処理します。
    • MapAssetは自動的に破壊されなくなりました。シーンのアンロード、リロードの際にMapAsset自体がみずから取り除くか、ご自身で気を配っておくようにしてください。
    • QuantumRunner.ShutdownはゲームオブジェクトをDestroy()し、OnDisable()がトリガーされ、それによりセッションが破壊されます。そして、OnGameDestroyed()コールバックがトリガーされます。以前は、ランナーがセッションを破壊するのは、次のUnityフレームの間だけでした。OnDestroy()の間、全てのスクリプトがシャットダウンしたゲームとともにもう一度実行されます。

C#

IEnumerator OnLeaveRoutine() {
  if (QuantumRunner.ShutdownAll()) {

    // ルームを出る
    PhotonNetwork.LeaveRoom();

    // 少し待つ (またはLeaveRoomを待つ)
    var startWait = Time.realtimeSinceStartup;
    while (PhotonNetwork.room != null && (Time.realtimeSinceStartup - startWait) < 1f) {
      yield return null;
    }

    // ..
}

SimulationConfig.Gravity

重力パラメータは3Dベクトルとなりました。2Dのゲームでは、XYの値は重力の情報に使用されます。カスタムコード内で重力を使用したり、直接x・yではなくベクトルとしてアクセスしている場合を除いて、変更は必要ありません。以下を参照してください。

C#

// 旧式
_settings->Gravity.SqrMagnitude

// 新式
_settings->Gravity.XY.SqrMagnitude

FPVector3.AsFPVector2 および FPVector2.AsFPVector3 を旧式としてマークしました。これは、選択したconventionの変換に混乱をきたすからです。 FPVector2 から FPVector3へ変換し、また元に戻すには明示的なプロパティを使用してください。

C#

struct FPVector3 {
    FPVector2 XY;
    FPVector2 XZ;
    FPVector2 YZ;
}

struct FPVector2 {
    FPVector3 XOY;
    FPVector3 XYO;
    FPVector3 OXY;
}

QuantumInputRecorderStarter.cs

QuantumInputRecorderStarterに関するロジックはQuantumGameクラスに移動しました。 RuntimeConfig.RecordingFlagsを設定して記録を開始し、QuantumGame APIをさらに全ての記録機能に使用します。

Console.Runnerプロジェクト

quantum.console.runnerをquantum_codeソリューションに移動しました。リプレイのデバッギング時に、「F5」キーですぐにブレークポイントに追加できるよう、近くにあったほうがいいからです。アップグレードファイルであるupgrade/quantum_code.zipには、完全なプロジェクトが含まれます。quantum_codeソリューションにcsprojを追加してください。ランナーはquantum_customソリューション内の旧式にいくつか修正をします(ループでの実行、チェックサム)。

ランナーは、直列化されたDBファイルである数値演算ルックアップテーブル(LUT)ファイルと、リプレイファイルおよび任意でチェックサムファイルを検索する必要があります。これらのファイルは、利便性からUnityプロジェクトのファイル(quantum_unity/Assets/Resources/replay)をポイントしています。詳細についてはupgrade/replay_notes.mdもしくはQuautumのオンラインドキュメントリプレイを参照してください。

1.2.0から1.2.1へ移行

ナビゲーションメッシュ

Quantum NavMeshの全てを再度ベイクします。

他のQuantumアセットと同じように、NavMeshも全てScriptableObject内で保存されました。NavMeshデータの大半は依然としてnavmeshアセットと共にバイナリファイルに保存されますが、非常にハンドリングしやすくなりました。ScriptableObjectのサイズ制限によって、まだ追加のバイナリファイルが必要です。

Assets/Resources/DB/MapName_NavMeshName.asset (new file)
Assets/Resources/DB/MapName_NavMeshName.bytes (similar to the file before, but some data is now saved on the asset file)

補完ファイルの読み込み方法にも変更を加えました。静的クラスFileLoaderを初期化して内部のQuantumコードに、どこからどうやってファイルを読み込むのか教える必要があります。これはQuantumRunner.csによって、既におこなわれていますが、ゲームシミュレーションのスタートルーティーンをカスタムしている場合に限り、手動で呼び出します。

Quantum.FileLoader.Init(new Quantum.UnityFileLoader());  

さらに、navmeshの内部構造も変更し、3Dデータを扱えるようにしました。3次元ナビゲーションマップに対応するためです。(ブリッジなど)

DSL: 生成されたエンティティフィールド

.qtnファイル内で、fieldsタグ下の全てのフィールドを個別のネストされた構造体にカプセル化する必要があります。これは、特定の条件会においてUnity外で.NETフレームワーク(リプレイなど)を使用してシミュレーションを実行する際に、依存している一連の構造体パッキングが再度順序付けられる可能性があるためです。(例えば、ネストされた構造体が明示的なレイアウトを使用する場合などです。)

新しくネストされた構造体へのアクセスは、エンティティ自身上のゲッターとセッターによって守られるようになりました。また、以下を実行している場合を除いて後方互換性があります。

C#

// エンティティフィールドにポインターを作成
var isDead = &mage->IsDead;         // コンパイルエラー
var isDead = &mage->Fields.IsDead;  // 新しい方法

// エンティティフィールドを参照として渡す
foo.bar(ref mage->IsDead)           // コンパイルエラー
foo.bar(ref mage->Fields.IsDead)    // 新しい方法

DSL:フレームのシリアル化

フレームオブジェクトはバイナリー形式にシリアライズ化されるようになりました。これはスナップショットベースの再接続にスナップショットを送る場合や、プラットフォームに依存しないチェックサムの生成にリクエストされる形式です。DSLによって自動的にシリアライゼーションコードは作成されますが、.qtnファイル内で使用しているインポートされた全てのカスタム構造体は静的メソッドSerialize(StructType* ptr, BitStream stream)を含む必要があります。

C#

[StructLayout(LayoutKind.Sequential, Pack = CodeGenConstants.STRUCT_PACK)]
public unsafe struct Foo {
    public Int32 Bar;

    public static void Serialize(Foo* ptr, BitStream stream) {
        stream.Serialize(ref ptr->Bar);
    }
}

Newtonsoft.Json

リプレイの保存と再生を有効にするには、アセットストアからJSON .NET For Unityというデフォルトパッケージをプラグインフォルダに追加してJSONシリアライゼーションを使用します。

quantum_unity/Assets/Plugins/JsonDotNet (new folder)

PUNフォルダ内にはこのDLLのバージョンがあり、 手動で削除する必要があります。以下を参照してください。

quantum_unity/Assets/Photon Unity Networking/Editor/PhotonNetwork/Newtonsoft.Json.dll (delete this file)

プロジェクトにJSON .NETプラグインを既に所有している場合は、どちらも削除してください。

参考: コンソールランナープロジェクトquantum_custom.slnはnugetを経由してNewtonsoft.Json依存で動作します。

物理レイヤーとマトリックス

物理レイヤーがシミュレーション設定アセットに保存され、手動でインポートする必要があります。以下を参照してください。

Physics Layers Image

以前のバージョンでは、アプリケーションの開始時にインポートされていましたが、パフォーマンスの低下につながるためUnity以外ではもはや実行されていませんでした。

QuantumRunner.StartGame()

カスタム設定を持たせてリプレイを実行するには、再度StartGame()のシグネチャを変更します。これにより構造体内の大部分のパラメータが結合されます。QuantumRunner.StartParameters.

構造体が前と同じ挙動となる設定にするため、見えるところに古いメソッドを置いておきます。

MapDataBakerCallback.OnBeforeBake

ベイキング手順が始まる前に実行される、別のコールバックメソッドが入力されました。例えばnavmesh生成をチェーンできるようにするためです。

App Id

AppIDが特定のプラグインバージョンにハードリンクされている場合があります。オンラインゲームの開始に問題がある場合は(シーンの読み込みができないなど)、下記の手順に従って新しいQuantum Appを作成してください。

## 1.1.8から1.2.0へ移行

これらのインストラクションは、1.1.8から新しい1.2.0のSDKを使用している既存のQuantumプロジェクトのポーティングを助けるものです。upgrade_instructions.txtに記載されている手順が完了していることを確認してください。

新しいApp Idの作成

Photon Cloudを接続するのに使用するApp IDは1.2.0と互換性を持つようにアップグレードする必要があります。
また、自動的に互換性を持つAppIDを新しく作成することもできます。以下の手順を参考にしてください。

  1. dashboardを表示します
  2. 新しいAppIdを作成します。
  3. manageボタンをクリックします。
  4. Create a new pluginをクリックします。
  5. saveをクリックします。

Unityコード生成

Quautumアセットのコード生成をUnityEditorからUnityのScriptableObjectsに移動し、スクリプトのコンパイルエラーが生じたときに実行できるようにしました。これはツールフォルダtools/codegen_unity/quantum.codegen.unity.host.exeにある実行ファイルで、quantum.systemプロジェクトのビルド後のイベントで呼び出されます。移行するにはビルド後のイベントを手動で追加します。以下を参照してください。

"$(SolutionDir)..\tools\codegen_unity\quantum.codegen.unity.host.exe" "$(TargetDir)\quantum.state.dll" "$(SolutionDir)..\quantum_unity\Assets"
  • Unityプロジェクトにカスタムネームやカスタムパスをつけている場合は,上記のラインの最後の部分を合うように変えてください。
  • 警告:生成されたフォルダ内の全てのスクリプトファイル(*.cs)はこの処理の間に削除されます。このフォルダ内にカスタムファイルを保管している場合は、移動してください。
  • Macを使用している場合は、monoコマンドの追加を忘れないようにしてください。

最後に、以下のファイルをプロジェクトリポジトリから削除します。

quantum_unity\Assets\Quantum\Editor\GenerateAssetScripts.cs

コードの変更 (RuntimePlayers)

Quantum APIで唯一の互換性を破る変更は、開発者がカスタムプロパティを RuntimeConfigおよびRuntimePlayerクラスに追加する際の方法とそのデータの予測セッションへのインジェクト方法(およびゲームクライアントの受信方法)に関係があります。

1.2.0より前ではマッチスタートの前にあらゆるカスタムデータを認識する必要があり、これにより全てのクライアントマシンは、RuntimeConfigとRuntimePlayerの各インスタンスの双方にローカルで同じデータをインジェクトしていました。(後から参加のデザインおよび実装が特に面倒なものになっていたのはこのためです)

はじめに、古い旧式のコードの作動を確認してから、新しいアプローチについてコードスニペットを用いて説明します。

旧式の方法: 1.1.8以前のSDK

RuntimeConfig と RuntimePlayerデータを初期化するためのサンプルコード(66-77行目はquantum.unity/Assets/Quantum/Lobby内のUIRoom.csから引用しました。)は、以下の通りです。

C#

RuntimeConfig config;
config = new RuntimeConfig();
config.Players = new RuntimePlayer[PhotonNetwork.room.MaxPlayers];

for (Int32 i = 0; i < config.Players.Length; ++i) {
    config.Players[i] = new RuntimePlayer();
}

config.Map.Guid = UnityDB.AllOf<MapAsset>().First(x => x.Settings.Scene == map).Settings.Guid;
config.GameMode = Photon.Deterministic.DeterministicGameMode.Multiplayer;

QuantumRunner.StartGame(config);

上記のコードは全てのゲームクライアントで実行される必要があり、もしゲームがRuntimePlayerインスタンス(プレイヤーのキャラクター選択など)ごとにカスタムデータをリクエストする場合には、Photonプレイヤープロパティなどを経由してこのコードを配布しなければなりませんでした。

そして、quantum.systemsに含まれるSystemクラス内のOnInitコールバック上でのあらゆるRuntimePlayerインスタンスを処理する通常の方法は以下の通りでした。

C#

public override void OnInit(Frame f)
{
    for (int i = 0; i < f.PlayerCount; i++)
    {
        var playerData = f.RuntimeConfig.Players[i];
        // ゲーム開始時、ここでのみプレイヤーデータを使用する
    }
}
新しい方法: 1.2.0以降のSDK

RuntimeConfig

RuntimeConfigの設定は同様に(使用される実際の値は、最初に接続したゲームクライアントからもしくはサーバーからオーバーホールされたもの)インジェクトされますが、RuntimePlayerはこの段階ではリクエストされません。

以下はRuntimeConfigを初期化するサンプルコードです。(66-70行目は quantum.unity/Assets/Quantum/Lobby内のUIRoom.csから引用しました。)

C#

RuntimeConfig config;
config = new RuntimeConfig();
config.Map.Guid = UnityDB.AllOf<MapAsset>().First(x => x.Settings.Scene == map).Settings.Guid;

QuantumRunner.StartGame(Guid.NewGuid().ToString(), PhotonNetwork.room.MaxPlayers, Photon.Deterministic.DeterministicGameMode.Multiplayer, config);

RuntimePlayerインスタンスをインジェクトする必要がなくなった点に留意してください。(ローカルプレイヤーに対しても必要ありません。)QuantumRunner.StartGame()のシグネチャも変更しました。

RuntimePlayer

RuntimePlayerデータの設定は、非同期プロセスとなりました。各ゲームクライアントはローカルプレイヤーに対して責任をもってRuntimePlayerインスタンスをQuautumにインジェクトし、Quantumは、シリアライズされたデータを予測にもとづいて配布します。

RuntimePlayerのインスタンス化とQuantumへの設定(サーバーに送信され、配信されます)はOnGameStartコールバックから(QuantumCallbacksを拡張するメニュースクリプトを作成することで)、またはセッション・QuantumGameが開始した後のどのUIコードからでも可能です。以下を参照してください。

C#

foreach (var lp in QuantumGame.Instance.GetLocalPlayers())
{
    QuantumGame.Instance.SetPlayerData(lp, new Quantum.RuntimePlayer { });
}

現在、クライアントごとにマルチプレイヤー用のサポートを追加しています。以降のバージョンで公開予定です。

ゲームクライアントは全員、新しいシグナル(ISignalOnPlayerDataSet)の同じティックでサーバーからRuntimePlayerインスタンスを受信するようになりました。以下を参照してください。

C#

public unsafe class SampleSystem : SystemBase, ISignalOnPlayerDataSet
{
    public void OnPlayerDataSet(Frame f, PlayerRef player)
    {
      RuntimePlayer playerData = f.GetPlayerData(player);
    }

    public override void Update(Frame f)
    {
    }
}

エンティティを作成したりプレイヤーのゲームステートコードを初期化する全てのコードは、 OnInitコールバックからこのシグナルにポートされる必要があります。

これにより、後からの参加が格段に簡単になります。新規で接続したプレイヤーがこのデータをゲームプレイ中のどのタイミングでも(以前のように開始時だけではなく)送信できるようになったからです。また、プレイヤーがカスタムRuntimePlayerインスタンスを何度も送ることも可能になりました。この機能は開発者が工夫して好きなように使うことができます。

カスタムデータのシリアライズ化 (RuntimeConfigおよびRuntimePlayer)

QuantumはRuntimeConfigもしくはRuntimePlayerクラスに追加された全てのカスタムデータを配布するようになったため、開発者は両方のクラスに追加された新しいシリアライゼーションコールバックに(例としてサンプルRuntimePlayerを使用して)回答する必要があります。以下の例ではサンプルRuntimePlayerを使用しています:

C#

partial class RuntimePlayer {

  public string myCustomData;

  partial void SerializeUserData(BitStream stream)
  {
    stream.Serialize(ref myCustomData);
  }
}

これらの手順をふむことで、Quantumの1.1.x~1.2.0のSDKで安全にそして簡単に既存のゲームをポートできるようになります。その他全てのAPI変更は新しく加わったものや最適化、または既存のコードの変更をリクエストしない新機能です。

Back to top