This document is about: QUANTUM 2
SWITCH TO

Frequently Asked Questions

大部分的常見問題的內容都衍生自開發者在#quantum-sdk-v2#beginner-questions的Discord聊天記錄中所問的問題。也可以使用聊天記錄的搜尋功能來找到更多協助。

Quantum Unity架構

如何重新命名Unity專案呢

  • **第一步:**以您所選的名字來重新命名quantum_unity文件夾。
  • **第二步:**以您在第一步所選的名字來編輯在quantum.code.csproj中的組建後事件的路徑。最簡單的方法是以文字編輯器開啟.csproj檔案,並且運行一個尋找並取代功能來將quantum_unity改成新的名稱。

為什麼以示範版本選單來開始遊戲時,遊戲場景未載入?

當伺服器拒絕應用程式帳號時,目前還沒有適當的錯誤訊息。請確保您已正確地建立您的應用程式帳號:

  1. 您的Photon儀表板建立一個Quantum應用程式帳號
  2. 按一下「建立一個新的應用程式」
  3. 將Photon類型設定成Photon Quantum
  4. 填寫名稱欄位
  5. 向下捲動並按下建立

為什麼在Quantum遊戲開始之前有一個1秒鐘的延遲?

請檢查您的Deterministic Config資產中的Room Wait Time (seconds)。您可以在那裡調整。房間等待時間 被用來處理變動Ping時間。
它在遊戲開始時將始終完全用於幫助同步所有客戶端遊戲階段。如果將其設定為1秒,它將始終等待整整1秒。

請注意: 這不應該用於同步場景載入時間!如果您需要協調這個,請在開始Quantum遊戲階段之前載入場景,並且直接透過Photon Realtime進行協調。在這個情形下,該值可以直接安全地設定為0。

為何在試著連接到Ns.exitgames.com的時候連接逾時?

為了取得更多資訊,請在您的PhotonServerSettings中增加連接記錄層級Network Logging。最常發生的是,逾時是由於您的UDP流量受阻。
如需取得如何分析您的情況的指引,請造訪Photon Realtime文檔中的分析無法連接頁面:分析無法連接

為什麼從NetworkPeer類別收到未處理事件警告?

102及103事件。

這些是在Session.Join()被調用之前所收到的時鐘同步及輸入訊息。客戶端將在加入模擬之後再次收到相關訊息。

本質上,您已經在房間準備好了,所以運行外掛程式遊戲階段在本地遊戲階段開始之前就發出訊息。

我可以整合我的Quantum解決方案到我的Unity專案中嗎?

在Unity 2019.4對應到Quantum 2.1及更高版本時是可行的。

tools\codeintegration_unity文件夾中的SDK中已包含一個README及一個逐步的指引。

**重要:**這是一個單向的轉換!

我該如何偵錯一個卡住的遊戲?

新增QUANTUM_STALL_WATCHER_ENABLED定義到Project Settings > Player > Scripting Define Symbols將啟用一個監控程式指令碼,以運行一個執行緒,其將監控更新迴圈。如果一個區位被偵測到(比如更新需要多於X秒鐘以被再次調用),它將建立一個當機。當偵錯模擬上的卡住的情形時,這是相當有用的,因為被生成的當機應該有來自所有運行的執行緒的調用堆疊。

為何不能在編輯模式中使用Quantum AssetRefs?

追隨AssetRef之前調用UnityDB.Init()。它可以被安全地調用許多次;這也包含當遊戲沒有運行的時候。
當在連結上使用執行個體收集器時,它試著使用儲存在連結上的GUID,來從Quantum DB中擷取Quantum資產。

是否有一個有效的方式,以在Unity編輯器中模擬運行遊戲時的網路延遲?

Quantum性能分析工具內建有一個延遲模擬。

請在此處下載:附加元件 | 分析工具

或使用一個外部網路節流工具,比如Clumsy(Windows作業系統),並且篩選出遊戲伺服器連接埠:

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

為什麼遊戲模擬在暫停或偵錯一個中斷點之後,運行的更快了?

在預設情況下,時間在內部被測量,而且也不補償暫停模擬。當模擬組態上的DeltaTimeType被改成EngineDeltaTime時,遊戲遊玩將在暫停之後恢復正常速度。警告:改變這個將使每個客戶端使用這個設定,如果只是用於偵錯的話,這可能不是理想的安排。雖然有些有著非常緊密的相機控制的遊戲(比如飛行模擬)將受益於將其設定為EngineDeltaTime

C#

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

為何我的WebGL組建卡住了?

請確保設定SiimulationConfig.ThreadCount1

為何我的WebGL組建很慢?

  • 請確保使用最新的Unity 2021版本以取得最佳性能。
  • Release組態中組建Quantum解決方案。
  • 試著在Unity中停用StackTrace,使用者報告說這樣有時候有用。

為什麼導航網格島嶼在我的幾何中被生成?

這將在某個時間由Unity進行修正(參見論壇文章:forum.unity.com/threads/nav-generating-inside-non-walkable-objects

透過導航網格修改程式磁碟區進行的因應措施,將幫助避免這個問題(需要導航網格元件)。

在匯入步驟進行三角揀選,是我們可以在未來提供的另一個替代方案。

Navmesh Island
### 為何我的遊戲在場景載入太久時,得到一個逾時取消連結?

當載入一個Unity場景時,縱使它是由LoadSceneAsync所完成,主要的執行緒可能根據該場景的大小或複雜度而卡住一段時間。這可能基於逾時而導致一個取消連結錯誤,原因是遊戲卡住時沒有發生通訊。

為了預防這樣的情況發生,您可以使用ConnectionHandler類別中提供的某些API。以下是設定並使用它的教學:

  • 檢查是否有任何附有ConnectionHandler元件的遊戲物件。如果沒有,請新增一個;

  • 在元件上,您將可以看到一個名為KeepAliveInBackground的欄位,您可以用它來增加維持連結的時間。該值以毫秒計算;

  • 您現在應該通知什麼是QuantumLoadBalancingClient,在此的UIMain上有一個靜態收集器,以防您使用它(在Quantum為預設)。當您完成這步時,您可以啟動StartFallbackSendAckThread。以下是一個範例程式碼片段,以說明如何完成:

C#

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

在Quantum中開發一個模擬

為什麼PhotonQuantum-Documentation.chm無法被讀取?

在Windows作業系統中下載SDK Zip檔案之後,您需要解除封鎖它:
右鍵按一下 > 屬性 > 勾選解除封鎖 > 完成

為什麼模擬以60幀開始?

這是可復原幀在模擬一開始時所配置的數字。該數字將符合確定性組態->復原視窗中所設定的數字。

為什麼Update()被以同樣的幀數調用了好幾次?

在系統上的Update()被以同樣的幀數調用了好幾次,以避免復原。當遠端玩家輸入的預測被偵測為不正確,而且模擬必須以正確的輸入資料重新運行一個幀,以回到一個決定性狀態時,將會發生這樣的情形。

如何在Visual Studio中偵錯指標?我只能看到位址。

  • 需要Unity 2018.4或更高版本,以及Visual Studio 2017。
  • 在我們的Unity專案中將Scripting Runtime Version設為.NET 4.x Equivalent
  • 確保您將您的Quantum DLL組建為Debug DLL。
  • 透過VS選單偵錯->附加Unity偵錯工具,來將Visual Studio附加到Unity,並且選擇正確的Unity編輯器執行個體。
  • 關閉所有VS及Unity編輯器的執行個體,啟動VS並重新組建Quantum DLL,然後開啟Unity並讓其重新載入,最後附加偵錯工具。

如何將編輯器附加到Unity(VS 2019)?

較新的Unity編輯器直接與PDB一同工作,但是他們不會刪除舊的已生成的MDB。為了強制進行更改並解決問題,請追隨這些步驟:

  1. 更改您的輸出偵錯資訊為可攜式。(以右鍵按一下Quantum.Code專案->開啟屬性->組建->進階)
  2. 從Unity刪除先前的Quantum DLL的MDB及PDB檔案。(資產/Photon/Quantum/組件)
  3. 組建您的Quantum專案。
  4. Unity現在應該從可攜式PDB重建MDB檔案,這應該有效。

FP.MaxValue和FP.UseableMax有什麼不同?

固定點數學只使用其64位元值的16+16位元。這使得數學的一部分更快,因為我們不需要檢查溢位。也就是說:FP.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操作手冊中的 條目。

浮點數數學

避免在模擬中使用浮點數,並且只使用FP數學。

謹慎處理FP.FromFloat_UNSAFE()。可以在「離線」時使用它,以在一台機器上平衡資產生成;然而,小心這樣做可能在不同的平台上得到不同的結果。如果您需要在運行階段時匯入浮點數,並且無法使用整數或FP(比如下載平衡資料),請從字串到FP進行轉換。

在Asset.Loaded()時建立的資料

在載入時,每個資產將調用一次Assets.Loaded()。可以在這個時候在資產成員中儲存、計算及儲存新資料——請注意: 如果您正在伺服器上運行模擬,所有遊戲將共享這一個資產。

如果您的資產從資源載入,並且您在運行階段時重新啟動Unity編輯器或重新設定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);
  }
}

我可以重新使用Photon Room,以同樣的客戶端建立新的Quantum遊戲階段嗎?

A) 不行,建議的而且簡潔的解決方案是切換房間

  • 直接使用Photon(比如房間屬性)在客戶端之間共享新的房間的帳號。
  • 停止Quantum遊戲階段。離開房間()但不取消連結。
  • 在客戶端上使用加入或建立()以連接到新的房間,以在每個客戶端同時進入時避免競爭情形。

配對指引

B) 可以,軟重新啟動您的遊戲

  • 保持Quantum遊戲階段的運行,縱使您的遊戲回合已經結束。
  • (可選擇)同時您可以確定性地停用Quantum系統。
  • 新增程式碼到您的處理遊戲回合重新啟動的遊戲遊玩系統(比如遊戲狀態機器)。
Back to top