Frequently Asked Questions
大部分的常見問題的內容都衍生自開發者在#quantum-sdk-v2
及#beginner-questions
的Discord聊天記錄中所問的問題。也可以使用聊天記錄的搜尋功能來找到更多協助。
Quantum Unity架構
如何重新命名Unity專案呢
- **第一步:**以您所選的名字來重新命名quantum_unity文件夾。
- **第二步:**以您在第一步所選的名字來編輯在quantum.code.csproj中的組建後事件的路徑。最簡單的方法是以文字編輯器開啟.csproj檔案,並且運行一個尋找並取代功能來將quantum_unity改成新的名稱。
為什麼以示範版本選單來開始遊戲時,遊戲場景未載入?
當伺服器拒絕應用程式帳號時,目前還沒有適當的錯誤訊息。請確保您已正確地建立您的應用程式帳號:
- 在您的Photon儀表板建立一個Quantum應用程式帳號
- 按一下「建立一個新的應用程式」
- 將Photon類型設定成Photon Quantum
- 填寫名稱欄位
- 向下捲動並按下建立
為什麼在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.ThreadCount
為1
為何我的WebGL組建很慢?
- 請確保使用最新的Unity 2021版本以取得最佳性能。
- 在
Release
組態中組建Quantum解決方案。 - 試著在Unity中停用
StackTrace
,使用者報告說這樣有時候有用。
為什麼導航網格島嶼在我的幾何中被生成?
這將在某個時間由Unity進行修正(參見論壇文章:forum.unity.com/threads/nav-generating-inside-non-walkable-objects)
透過導航網格修改程式磁碟區進行的因應措施,將幫助避免這個問題(需要導航網格元件)。
在匯入步驟進行三角揀選,是我們可以在未來提供的另一個替代方案。
### 為何我的遊戲在場景載入太久時,得到一個逾時取消連結?當載入一個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。為了強制進行更改並解決問題,請追隨這些步驟:
- 更改您的輸出偵錯資訊為可攜式。(以右鍵按一下Quantum.Code專案->開啟屬性->組建->進階)
- 從Unity刪除先前的Quantum DLL的MDB及PDB檔案。(資產/Photon/Quantum/組件)
- 組建您的Quantum專案。
- Unity現在應該從可攜式PDB重建MDB檔案,這應該有效。
FP.MaxValue和FP.UseableMax有什麼不同?
固定點數學只使用其64位元值的16+16位元。這使得數學的一部分更快,因為我們不需要檢查溢位。也就是說:FP.MinValue
及FP.MaxValue
使用所有64位元,並且應該 永不 被用於計算。使用FP.UseableMax
及FP.UseableMin
作為替代(例如以最小FP值來初始化一個距離變數)。
請注意: FP可以代表-32,768到32,768的值(-2¹⁵到2¹⁵)。
為什麼一個新的架構的指標指向過時資料?
在迴圈裡面,一個架構的指標獲得同樣的堆疊指標,並且在new
或default
都 沒有 被使用的情況下,將包含過時資料。
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系統。
- 新增程式碼到您的處理遊戲回合重新啟動的遊戲遊玩系統(比如遊戲狀態機器)。
- Quantum Unity架構
- 如何重新命名Unity專案呢
- 為什麼以示範版本選單來開始遊戲時,遊戲場景未載入?
- 為什麼在Quantum遊戲開始之前有一個1秒鐘的延遲?
- 為何在試著連接到Ns.exitgames.com的時候連接逾時?
- 為什麼從NetworkPeer類別收到未處理事件警告?
- 我可以整合我的Quantum解決方案到我的Unity專案中嗎?
- 我該如何偵錯一個卡住的遊戲?
- 為何不能在編輯模式中使用Quantum AssetRefs?
- 是否有一個有效的方式,以在Unity編輯器中模擬運行遊戲時的網路延遲?
- 為什麼遊戲模擬在暫停或偵錯一個中斷點之後,運行的更快了?
- 為何我的WebGL組建卡住了?
- 為何我的WebGL組建很慢?
- 為什麼導航網格島嶼在我的幾何中被生成?
- 在Quantum中開發一個模擬