Quantum Intro
概述
現在可下載和使用2.0 SDK。
我們也打造了更快的版本更新流程,其中我們將為永久可用的「已標幟」版本+每夜組建版加上標記,以立即取得最新的錯誤修正及新功能:請造訪SDK下載章節。
Photon Quantum是高性能的確定性ECS(實體元件系統)架構,適用於以Unity製作而成的線上多重玩家遊戲。
它基於預測/復原方法,這很適合對於延遲敏感的線上游戲,比如動作角色扮演遊戲、體育遊戲、格鬥遊戲,第一人稱射擊遊戲及其他更多遊戲。
Quantum也幫助開發者撰寫整潔的程式碼,模擬邏輯(Quantum ECS)完全地從檢視/展示(Unity)分離,同時也兼顧了網路執行方式詳細規格(內部預測/復原+傳輸層+適用不同遊戲的伺服器邏輯):
Quantum執行最先進的技術堆疊,其由以下項目組成:
- 由伺服器管理的預測/復原模擬核。
- 疏鬆集ECS記憶體模型及API(SDK第2版的新功能)。
- 無狀態確定性程式庫的完整集(數學、2D及3D物理、導航等等)。
- 豐富的Unity編輯器整合及工具。
所有項目都組建在成熟及業界公認的現有Photon產品及基礎架構之上(Photon即時傳輸層、Photon伺服器外掛程式到主機伺服器邏輯等等);
SDK第2版的新功能
Quantum 2在久經考驗的第1.2版本所建立的基礎上帶來重大的改進。整個技術堆疊都經過修正及重新組建,以啟用由客戶及內部開發者團隊所展望的功能。
以下這些是最重要的新功能(將SDK 2.0 RC與SDK 1.2.4.1相比之後):
- 疏鬆集ECS記憶體模型,附有動態實體及元件(新增/移除)以替換靜態類別的由程式碼生成的實體。
- 新增由資料驅動的實體原型,可儲存於Quantum DB資產或直接儲存於Unity場景之中(內嵌於地圖資產中)。
- 動態集合架構,對於復原附有完整支援(儲存於新的自訂堆積配置器中)。
- 對於執行緒而言安全的DB資產物件的動態載入,包含確定性按需同步或背景非同步預先載入,以及運行階段記憶體消耗控制的完整處理。
- 2D及3D物理引擎內核已被重新改寫,附有一個完全平行寬相位、先發的查詢及許多其他的性能改進及功能(接合、進入/停留/離開回調等等)。
- 全新工作系統同時在內部使用及公開給進階客戶使用(系統本身就是工作,能夠自由地排程工作相依性等等)。包含一個全方位的使用者介面作為我們的工作分析工具。
- 從選單場景範例指令碼中移除對於PUN的相依性(Quantum現在內嵌更精簡的Photon Realtime C#傳輸層的最新版本)。
確定性而沒有鎖步
在確定性系統中,遊戲客戶端只能透過在所有客戶端上本地的運行模擬的方式交換玩家輸入。在過去,這已使用一種鎖步的方式,其中遊戲客戶端在更新模擬的每次刷新/幀之前,將等待所有其他玩家的輸入。
然而在Quantum中,遊戲客戶端能夠自由的使用輸入預測在本地中推進模擬,而且一個進階的復原系統將處理遊戲狀態的還原及重新模擬任何錯誤預測。
由於Quantum也依靠一個跨遊戲平台的權威伺服器元件(Photon伺服器外掛程式)以管理輸入延遲及時鐘同步處理,因此客戶端永遠不需要等待最慢的客戶端,就能向前進行模擬的復原/確認:
以下這些是一個Quantum遊戲的基本組建區塊:
- Quantum伺服器外掛程式:管理遊戲客戶端之間的輸入時間和傳遞,作為時鐘同步源。
可被擴展以與自訂主機端的後端系統(配對、玩家服務等等)整合。 - 遊戲客戶端模擬器:與Quantum伺服器通信,運行本地模擬,執行所有輸入預測和復原。
- 自訂遊戲遊玩模式:由客戶開發,作為一個使用Quantum ECS的獨立的純C#模擬(從Unity分離)。
除了提供一個架構以組織高性能的程式碼之外,Quantum的API也提供大量的預先組建的元件(資料)及系統(邏輯),可在任何遊戲中重新被使用,比如確定性3D向量數學、2D及3D物理引擎、導航網格導航器等等。
傳統式編碼
所有模擬程式碼都必須有著立即可用的高性能,Quantum內部系統都以這樣的理念從頭開始設計。
Quantum的高性能的關鍵在於使用了基於指標的C#程式碼,並結合其疏鬆集ECS記憶體模型(所有基礎記憶體對齊資料架構,以及自訂堆積配置器——在運行階段時模擬程式碼沒有記憶體回收)。
目標是將大部分的CPU資源留給檢視/轉譯程式碼(Unity),其中包含預測/復原方法本身所固有的,輸入錯誤預測所引發的重新模擬:
雖然基於指標的C#程式碼的使用被公開(以達成性能),透過聰明地使用自訂DSL及自動程式碼生成,大部分的複雜性仍對開發者隱藏,。
程式碼生成
在Quantum中,所有遊戲遊玩資料(遊戲狀態)都保存在疏鬆集ECS資料架構(實體及元件)或在我們的自訂堆積配置器(動態集合和自訂資料),資料永遠都是可直接複製的且與記憶體對齊的C#架構。
為了定義這些資料架構,開發者使用一個自訂DSL(特定領域語言),以讓開發者專注於遊戲概念而非困於性能限制:
C#
// components define reusable game state data groups
component Resources
{
Int32 Mana;
FP Health;
}
// structs, c-style unions, enums, flags, etc, can be defined directly from the DSL as well
struct CustomData
{
FP Resources;
Boolean Active;
}
以上的程式碼片段將生成對應的類型(與明確的記憶體對齊),序列化程式碼,以及一個針對特殊類型(比如元件)的適用於全平台的控制邏輯。
自動生成的API讓您以全面的功能來查詢及修正遊戲狀態,如逐一查看、修正、建立和消除實體(基於組合):
C#
var es = frame.Filter<Transform3D, Resources>();
// Next fills in copies of each of the components + the EntityRef
while (es.NextUnsafe(out var entity, out var transform, out var resources)) {
transform->Position += FPVector3.Forward * frame.DeltaTime;
}
無狀態系統
雖然Quantum的DSL以實體、元件及輔助架構(架構、列舉、等位、位集、集合等等)等概念來處理遊戲狀態資料定義,仍需要一個方式來組織負責更新遊戲狀態的自訂遊戲邏輯。
您透過執行系統來撰寫自訂邏輯,這是邏輯的無狀態片段,將由Quantum的客戶端模擬迴圈在每次刷新更新時執行:
C#
public unsafe class LogicSystem : SystemMainThread
{
public override void Update(Frame f)
{
// your game logic here (f is a reference for the generated game state container).
}
}
系統API遊戲迴圈調用順序、系統間溝通(自訂及預先組建,比如物理引擎衝突回調)的信號、事件及幾種其他的擴充勾點
事件
雖然模擬是在純C#中執行,而沒有直接參照Unity的API,仍有兩個重要的功能以讓遊戲遊玩程式碼能與轉譯引擎通信:事件及資產連結系統。
事件是一個方法,以讓遊戲程式碼將模擬時發生的重要事情通知轉譯引擎。
比如當某件事情對角色造成傷害的情況。
使用來自先前的區段的狀態作為基礎,假設傷害減少了角色實體的資源元件的健康值。
來自Unity轉譯指令碼,唯一重要的資料將是新的健康值,不需要任何方式去知道導致傷害的原因及先前的健康值是什麼等等。
在一個檔案DSL中的事件定義:
C#
event Damage
{
entity_ref Character;
FP Amount;
}
遊戲遊玩程式碼以一個簡單的API調用(已生成)來引發事件:
C#
public void ApplyDamage(Frame f, EntityRef c, FP amount)
{
// missing here, the logic to apply damage to the character itself
// this sends an event to the "view" (Unity)
f.Events.Damage(amount, c);
}
在刷新更新完成之後,Quantum的事件處理器將處理所有已生成的事件,處理需要伺服器確認的輸入的事件,事件重複,以及當模擬復原發生時也處理取消/確認。
從模擬程式碼引發的事件,之後可在運行階段從Unity指令碼中所建立的回調來使用:
C#
public void OnDamage(DamageEvent dmg)
{
// instantiate and show floating damage number above the target character, etc
}
資產連結
Unity為人所知的是其充滿彈性的編輯器及平順的資產管線。
資產連結系統允許遊戲及關卡設計師從Unity編輯器來建立和編輯由資料驅動的模擬物件,這之後又輸入到模擬之中。
這對於原型來新增最終平衡修飾到遊戲遊玩中來說是必要的。
從C#模擬專案,開發者建立一個由資料驅動的類別,公開了所需的屬性:
C#
public partial class CharacterClass
{
public Int32 MaxMana;
public FP MaxHealth;
}
之後從Unity類別,設計師可以按照需要的數量來建立這個資產的執行個體,各個執行個體都自動被指派一個獨一無二的GUID:
之後,程式設計師可以直接從模擬內部使用來自這些資產的資料:
C#
var data = frame.FindAsset<CharacterClass>("character_class_id");
var mana = data.MaxMana;
也可以在來自狀態定義DSL的元件中直接參照這些資產:
C#
component CharacterAbilities
{
asset_ref<CharacterClass> CharacterData;
}
確定性程式庫
在Quantum中,模擬需要在所有客戶端上計算同一個結果,前提是他們使用同樣的輸入值。
這意味著它必須是確定性,這代表不能使用任何浮點數或雙精度浮點數變數,也不能使用任何來自Unity API的功能,比如他們的向量、物理引擎等等。
為了幫助遊戲開發者執行這種遊戲遊玩風格,Quantum與一個有彈性的且可擴展的確定性程式庫進行配套,兩者都附有一個類別/架構/功能的集,以及一些當以DSL定義實體時可直接使用的元件。
以下模組都可用:
- 確定性數學程式庫:FP(固定點)類型(Q48.16)以取代浮點數或雙精度浮點數、FPVector2、FPVector3、FPMatrix、FPQuaternion、RNGSession,、FPBounds2,以及所有額外的數學公用程式包含安全投射,以及來自原生類型的剖析器。
數學程式庫以性能作為主要目標來執行,所以我們盡可能地大量使用了內嵌、查閱資料表及快速運算子。 - 2D及3D物理引擎:高性能無狀態2D/3D物理引擎並支援靜態及動態物件、回調、接合等等。
- 導航網格/導航器/代理程式:包含來自現有的Unity導航網格的匯出工具,或直接操控網格的編輯器。也包含符合行業標準的HRVO衝突避免工具、呈漏斗狀的路徑,以及更多其他功能。
還有很多需要學習的地方,所以我們建議看一下此文件的操作手冊部分。
Back to top