This document is about: QUANTUM 2
SWITCH TO

よくある質問

FAQ の内容のほとんどは、#quantum-sdk-v2#beginner-questions の Discord チャットで開発者が質問したものです。より多くのヘルプを見つけるには、検索機能を使ってください。

Quantum Unity フレームワーク

Unityプロジェクトの名前変更はどのように行えますか? project

  • ステップ1: quantum_unityフォルダを自分の選んだ名前に変更します。
  • ステップ2: quantum.code.csproj でポストビルドイベントのパスをステップ1で選択した名前に編集します。もっとも簡単な方法は、.csprojファイルをテキストエディタで開いて検索と置換でquantum_unityを新しい名前に変更します。

デモメニューからゲームを起動してもゲームシーンが読み込まれないのはなぜですか?

AppIdがサーバーによって拒否された場合、適切なエラーメッセージはまだありません。AppIdが正しく作成されていることを確認してください。

  1. PhotonダッシュボードでQuantum App Idを作成します。
  2. CREATE A NEW APPをクリックします。
  3. Photonの種類を Photon Quantum に設定します。
  4. 名前の欄に記入します。
  5. 下にスクロールしてCREATEを押します。

Quantumゲームが始まるまでに1秒の遅延があるのはなぜですか?

Deterministic Configアセットの Room Wait Time (seconds) をチェックしてください。ここで微調整することができます。ルーム待ち時間 はping時間の変動に対応するために使われます。
これは、開始時にすべてのクライアントセッションを同期させるために常にフルで使用されます。1秒に設定した場合は、1秒間待機します。

備考: これはシーンの読み込み時間を同期させるために使用すべきではありません。調整する必要がある場合は、Quantumセッションを開始する前にシーンを読み込み、Photon Realtimeを通じて直接調整してください。今回の場合は、この値は安全に0に設定することができます。

ns.exitgames.comに接続しようとしている間、接続がタイミングアウトしてしまうのはなぜですか?

より詳細な情報を得るには、PhotonServerSettingsの接続ログレベル Network Logging を上げてください。ほとんどの場合、タイムアウトはUDPトラフィックがブロックされていることが原因です。
状況の分析方法については、Photon RealtimeのドキュメントのAnalyzing Disconnectsページを参照してください。 Analyzing Disconnectsを参照してください。

NetworkPeer クラスから処理されないイベントの警告が表示されるのはなぜですか?

イベント102と103。

これらは、Session.Join()が呼ばれる前に受信したクロック同期と入力メッセージです。クライアントはシミュレーションに参加した後、関連するメッセージを再び受け取ることになります。

基本的に、すでにルームの中にいるので、実行中のプラグインセッションは、ローカルセッションが開始される前でもメッセージを送信します。

Quantum SolutionをUnityプロジェクトに統合することはできますか?

Unity 2019.4でQuantum 2.1以降で可能です。

ステップバイステップのガイドを含む README がSDKの toolscodeintegration_unity フォルダに含まれています。

重要: これは一方向の変換です!

フリーズしたゲームをデバッグする方法は?

QUANTUM_STALL_WATCHER_ENABLED定義を Project Settings > Player > Scripting Define Symbolsに追加すると、Watcher スクリプトが Update ループを監視するスレッドをスピンアップすることができるようになります。ストール(Updateが再び呼び出されるまでにX秒以上かかること)が検出されると、クラッシュを発生させます。生成されたクラッシュには実行中のすべてのスレッドのコールスタックが含まれるため、シミュレーションのデバッグがフリーズした場合に便利です。

編集モードでQuantum AssetRefsが使えないのはなぜですか?

AssetRefをフォローする前にUnityDB.Init()を呼び出してください。これは、ゲームが実行されていないときも含めて、安全に複数回呼び出すことができます。
リンク上で Instance ゲッターを使用すると、リンク上に保存されている GUID を使用して Quantum DB から Quantum アセットを取得しようとします。

Unity Editorでゲームを実行する際に、ネットワークのレイテンシをシミュレートする効果的な方法はありますか?

Quantumのパフォーマンスプロファイラにはレイテンシシミュレーションが搭載されています。

ここからダウンロード: AddOns | Profiler

または、Clumsy (Windows)などの外部のネットワークスロットリングツールを使用してゲームサーバーポートをフィルタリングできます。

  • UDP 5056
  • TCP 4531
Clumsy Filter: (udp.DstPort == 5056 or udp.SrcPort == 5056) or (tcp.DstPort == 4531 or tcp.SrcPort == 4531)

ブレイクポイントのポーズまたはデバッグ後の方がゲームシミュレーションの速度が上がるのはなぜですか?

デフォルトでは、時間は内部的に計測され、シミュレーションを中断しても補正されません。SimulationConfigのDeltaTimeTypeEngineDeltaTimeに変更すると、一時停止後は通常の速度でゲームが再開されます。警告: この設定を変更すると、すべてのクライアントがこの設定を使用することになり、デバッグのためだけに使用する場合には好ましくありません。ただし、非常にタイトなカメラコントロールのゲーム(例: フライトシミュレーション)では、EngineDeltaTimeに設定すると有効です。

C#

public enum SimulationUpdateTime {
    Default = 0,                        // internal clock
    EngineDeltaTime = 1,                // Time.deltaTime (Unity)
    EngineUnscaledDeltaTime = 2         // Time.unscaledDeltaTime
}

Why is my WebGL build freezing?

Make sure the set SiimulationConfig.ThreadCount to 1

Why is my WebGL build to slow?

  • Make sure to use latest Unity 2021 version for best performance.
  • Build the quantum solution in Release configuration.
  • Try to disable the StackTrace in Unity, users reported this helps sometimes.

これはいつかUnityで修正される予定です(フォーラムの投稿を参照してください:forum.unity.com/threads/nav-generating-inside-non-walkable-objects)

NavmeshModifierVolumeでの回避策はこれを軽減します([NavMeshComponents](https://github.com/Unity-Technologies/NavMeshComponents)が必要)。

インポートステップ中の三角形カリングは、将来提供できるもう1つの方法です。

### シーンの読み込みに時間がかかりすぎると、ゲームがタイムアウトで切断されるのはなぜですか?

Unity のシーンを読み込むとき、たとえ LoadSceneAsync で行われたとしても、シーンのサイズや複雑さに応じてメインスレッドがしばらくの間フリーズすることがあります。このとき、ゲームがフリーズしている間は通信が行われないので、タイムアウトによる切断エラーになることがあります。

これを防ぐために、ConnectionHandlerクラスで提供されているAPIの一部を使用することができます。以下、設定方法と使い方をステップバイステップで説明します。

  • ConnectionHandler コンポーネントのGame Object が存在するかどうか確認してください。ない場合は、追加してください。

  • コンポーネントには KeepAliveInBackground というフィールドがあり、接続を維持する時間を増加させることができます。値はミリ秒単位で通知されます。

  • QuantumLoadBalancingClient を使用する場合は、 UIMain に静的なゲッターがあります (デフォルトで Quantum に付属しています)。これができたら、StartFallbackSendAckThread を開始できます。以下は、それを実現するためのサンプルスニペットです。

C#

    // Before starting loading the scene
    if (_connectionHandler != null)
    {
      _connectionHandler.Client = UIMain.Client;
      _connectionHandler.StartFallbackSendAckThread();
    }

Quantumシミュレーションの開発

シミュレーションがフレーム60から始まるのはなぜですか?

これは、シミュレーションの開始時に割り当てられるロールバック可能なフレーム数です。この数はDeterministicConfig->Rollback Windowで設定した値と一致します。

Update() が同じフレーム番号で複数回呼び出されるのはなぜですか?

システムのUpdate()は、ロールバックが発生した場合、同じフレーム番号に対して複数回呼び出されます。これは、リモートプレイヤーの入力の予測が正しくないことが検出され、シミュレーションが決定論的な状態に戻るために正しい入力データでフレームを再実行しなければならない場合に発生します。

Visual Studioでポインタをデバッグするには?アドレスしか見あたりません。

  • Unity 2018.4以上、Visual Studio 2017が必要です。
  • Unityプロジェクトの Scripting Runtime Version.NET 4.x Equivalentに設定する。
  • QuantumのdllはDebugのdllとして構築してください。
  • Visual Studio を VS メニューの Debug->Attach Unity Debugger で Unity に添付し、正しい Unity Editor インスタンスを選択します。
  • VSとUnity Editorのすべてのインスタンスを閉じ、VSを起動してQuantum dllを再構築し、Unityを起動して再読み込みさせ、デバッガを添付します。

Unity (VS 2019)にエディタをアタッチするにはどうしたらいいですか?

新しいUnityエディタは直接PDBで実行できますが、生成された古いMDBを削除することはしません。強制的に変更してこの問題を解決するには、以下のステップに従ってください。:

  1. 出力デバッグ情報をPortableに変更します。(Quantum.Codeプロジェクト→Open Properties->Build->Advancedを右クリックで進みます。)
  2. Unityから前回のquantum dll、mdbファイル、pdbファイルを消去します。(Assets/Photon/Quantum/Assemblies)
  3. quantumプロジェクトをビルドします。
  4. Unityがポータブルpdbからmdbファイルを再ビルドするようになり、無事に実行できるはずです。

FP.MaxValueとFP.UseableMaxの違いは?

定点演算では、64ビットの値のうち16+16ビットのみを使用します。オーバーフローをチェックする必要がないため、計算の一部が高速になります。つまり、FP.MinValueFP.MaxValueFP.MinValueFP.MaxValue は64ビットすべてを使用しており、計算には一切使用すべきではありません。代わりに FP.UseableMaxFP.UseableMin を使ってください (たとえば距離変数を最小FP値で初期化する場合など)。

備考: FPは、-32,768~32,768(-2¹⁵~2¹⁵)の値を表すことができます。

新しい構造体へのポインタが古いデータを指すのはなぜですか?

newdefaultが使われていない場合、ループ内では、構造体へのポインタは同じスタックポインタを取得し、は古いデータを含んでしまいます。

C#

struct Bar {
    public bool Foo;
}

static unsafe void Main(string[] args) {
    for (int i = 0; i < 2; i++) {

        Bar bar;
        //Bar bar = default(Bar); // <---- Fixes the stale data

        Bar* barPt = &bar;
        if (barPt->Foo)
            Console.WriteLine("Stuff and Things");

        barPt->Foo = true;
    }

    Console.ReadKey();
}

シミュレーションが非同期になってしまいます。

DeterministicConfig.ChecksumIntervalが > 0 の場合、検証済みのフレームのチェックサムが計算され、サーバに送信され、他のクライアントが送信したチェックサムと比較されます。

最も多い原因は以下です:

#### Quantumデータアセットへの書き込み

C#

c->CharacterSpec = DB.FindAsset<CharacterSpec>("WhiteFacedBarghast");
c->CharacterSpec.RemainigLifetime = 21;

Quantumアセットには何も書き込まないでください。読み取り専用のデータが含まれています。

UnityスレッドからQuantumへの書き込み

Unityのすべてのスクリプトは、Quantumフレームを通して公開されているすべてのものに読み取り専用でアクセスすることができます。入力および/またはコマンドによってのみシミュレーションに影響を与えます。

データのキャッシュ

以下のコードスニペットは、シミュレーションがロールバックされたときに、最終的に非同期になります。

C#

public class CleaningSystem : SystemBase {
    public Boolean hasShoweredToday;    // <----- Error
    public override void Update(Frame f) {
        if (!hasShoweredToday && f.Global->ElapsedTime > 100) {
            Shower();
            hasShoweredToday = true;
        }
    }
}

代わりに、非一時的なデータをフレームまたはエンティティ コンポーネントに保存します。

C#

// Frame
unsafe partial class Frame {
    public Boolean HasShoweredToday;
    partial void CopyFromUser(Frame frame) {
        // Implement copy of the custom parameters.
    }
}

public class CleaningSystem : SystemBase {
    public override void Update(Frame f) {
        if (!f.HasShoweredToday && f.Global->ElapsedTime > 100) {
            Shower();
            f.HasShoweredToday = true;
        }
    }
}

詳細については、Quantum v2 マニュアルの Frames エントリを参照してください。

浮動小数点演算

シミュレーションの内部では浮動小数点数を使用せず、FPの演算のみを使用してください。

.FromFloat_UNSAFE() の取り扱いには注意してください。1台のマシン上でアセットを生成するためにこれをオフラインで使用することは問題ありませんが、プラットフォームによって異なる結果を返す可能性があることに注意してください。実行時にフロートをインポートする必要があり、整数やFPを使用できない場合(バランシングデータのダウンロードなど)は、StringからFP に変換してください。

Asset.Loaded()中に作成されたデータ

Assets.Loaded()は、アセットの読み込み中に1アセットにつき1回呼び出されます。この時にアセットメンバー内に新しいデータを格納したり、計算したり、保存したりしても全く問題ありません。備考:サーバー上でシミュレーションを実行している場合、全てのゲームでこの1つのアセットを共有しています。

アセットがリソースから読み込まれていて、実行時にUnity Editorを再起動するかUnity DBをリセットしている場合、UnityはUnityアセットをアンロードしないので注意してください。

C#

public partial class FooAsset : AssetBase {
  public Foo Settings;
  public int RawData;

  [NonSerialized]
  public List<int> Bar = new List<int>();

  public override AssetObject AssetObject => Settings;

  public override void Loaded() {
    // This will break on the second run (see above) because Bar needs to be reset by either Bar.Clear() or Bar = new List<int>()
    Bar.Add(RawData);
  }
}

同じクライアントとの新しいQuantumセッションでPhotonルームを再利用することはできますか?

いいえ、別のQuantumセッションにルームを再利用するべきではありません。

ただし、プレイヤー(全員または一部)をルーム内に保持し、シミュレーションをソフト再起動することは可能です。この方法で、Stumble Guysは3つのステージ間で進行しています。

  • ゲームラウンドが終了しても、Quantumセッションを実行し続けてください。
  • ゲームプレイシステムに(例:ゲームステートマシン)、ゲームラウンドの開始を処理するコードを追加します。
  • Quantumシステムを決定論的に無効化し、および/または新しいQuantumマップをロードします。
  • すべてのQuantumエンティティをリセットまたは破壊し、ゲームビューをリセットします。
  • ラウンドに負けたプレイヤーは、接続を維持して試合を観戦することはできますが、ゲームに影響をおよぼすことはできなくなります。

代替案として、全てのプレイヤーが部屋を交換することができます。ただし、この方法の場合にはサーバーの移行が必要となり、分散システムでは多くの障害が発生する可能性があるため、まずはシミュレーションのソフト再起動を試み、最後の手段としてルームの移行をおこなうことが推奨されています。

  • 新しいルームのIDをクライアント間で共有します(例:PhotonルームプロパティまたはQuantumコマンドを使用)。または、プログラム的に/決定論的に新しいルームを作成します(これは、簡単に推測されないように留意してください)。
  • 全てのクライアントはQuantumセッションを停止し、LeaveRoom()を実行しますが、接続は切断しません。
  • すべてのクライアントはJoinOrCreate()を使用して、新しいルームに接続します。
  • 処理中にクライアントがアプリを再起動する、その他の接続エラー、プレイヤーの参加待ちなど、接続にまつわる問題を軽減します。

Photon Realtimeマッチメイキングガイドを参照してください。

DSLで生成したunion構造体を、Quantumアセットで使用することはできますか?

直接はできません。Unityはオーバーラップするフィールドをサポートしていません。

代わりに<UnionName>_Prototypeが使用できます。これはUnityでシリアライズ可能で、ドロワーを備えています。

以下のように、union―構造体に変換することができます:

C#

UnionName result = default;
prototype.Materialize(frame, ref result, default);
Back to top