跳至主要內容
SheetForge

核心概念

試算表是唯一真實來源

你的資料只會有一種權威形式:試算表。其他一切都是由此衍生而來:

  • IR(不可變的定義)是試算表經過驗證、組裝後的形式。
  • 產生的 C# 類別是 IR 結構描述的強型別化呈現。
  • 烘焙後的 ScriptableObject 是 IR 數值的可載入呈現——是一個查詢用快取,絕不是獨立的真實來源。

所有修改都必須透過試算表進行,並通過重新匯入的驗證後才會生效。直接編輯烘焙後的 SO 會製造出第二個真實來源,並繞過驗證——本產品刻意不將其支援為一種工作流程。(檢閱器中的「測試編輯」切換開關是為了暫時性的執行期實驗而存在;它絕不會被寫回,且重新匯入會將其清除。)

為什麼這很重要:把 SO 當成真實來源的專案,最終會出現未經驗證的資料逐漸偏離試算表、且無法調解的情況。在這裡,調解是結構性的——永遠從試算表重新產生。

IR——不可變、經過驗證的組裝結果

IR 是驗證所產生的結果。針對每個分頁,都會產生一個 SheetTable(結構描述 + 記錄),其儲存格已是具型別的值(intfloat、enum 值、記錄參照、資源參照、清單、自訂外掛型別)。

關鍵特性:

  • 不會有部分組裝的結果。 只要任何地方存在單一錯誤,就不會建構 IR(ImportResult.Success == false ⇔ Registry == null——這是一項硬性不變條件)。
  • 沒有 null。 空白的選填儲存格會立即實體化為其型別的預設值,並標記為 IsDefaulted——使用端絕不需要進行 null 檢查。
  • 不可變。 IR 組裝完成後即為唯讀;各出口(程式碼產生、烘焙、匯出)只會讀取它,絕不會修改它。

管線

fetch → parse markers/schema → parse cells → validate (keys, references,
@overlap, asset keys, domain rules) → assemble IR → codegen (.cs) → bake (SO)
       └──────────────── collect ALL diagnostics ────────────────┘
  • 驗證會蒐集一切。 你會在一次執行中得到完整的問題清單——每個錯誤各自附上在哪裡/是什麼/為什麼/怎麼修——而不必每次重新匯入只修一個錯誤。
  • 程式碼產生是最後一個階段,發生在驗證與數值組裝之後,因為寫入 .cs 檔案會觸發網域重新載入。此管線的結構設計確保了重新載入是安全的,且流程鏈會在其後自動接續。
  • 錯誤是結構化物件,並以句子形式呈現。 每個錯誤都帶有分頁、從 1 開始計數的列、欄字母及欄位名稱、有問題的值、違反的規則,以及可據以行動的建議(針對拼字錯誤會提供最接近的候選建議)。同一批物件也能以機器可讀座標的形式,呈現於紀錄檔/CI 中。

自動匯入鏈

當結構描述是新的或有變動時,一次匯入在內部會執行:

  1. 寫入產生的程式碼 → Unity 進行編譯 → 網域重新載入。
  2. 重新載入之後,此流程鏈會自行接續並完成烘焙。

你完全不需要手動重新觸發任何動作。如果編譯失敗(例如你的遊戲程式碼參照了一個剛被重新命名變更過的欄位),此流程鏈會安全中止,並在 Console 提供一句可據以行動的說明,而不會陷入迴圈(重試上限為 3 次,並有接續紀錄)。

強型別化,無執行期剖析

程式碼產生器會讀取 @name / @type / @desc,並針對每個分頁 Foo 產生:

  • FooDefinition——一個強型別的 record 類別,每欄對應一個欄位;@desc 會成為 XML 檔案註解與檢閱器工具提示。
  • FooDatabase : DefinitionDatabase——每個分頁專屬的容器 SO,內含 Records、延遲載入的 id 查詢,以及 SchemaFingerprint

烘焙會寫入真正具型別的欄位——零執行期文字剖析、無執行期反射,因此對 IL2CPP 是安全的(沒有程式碼剝離風險)。

位址載入——快取如何保持可共享

烘焙後的 SO 是依機器而異的快取,具有依機器而異的 GUID。直接以場景參照它們,會在不同機器間失效。因此改為:

  • 匯入會自動將每個 Database SO 註冊到 Addressables 群組 SheetForge 中,位址為穩定的 "SheetForge/{tab}"(重新烘焙時,會將新的 GUID 重新連結到同一個位址;已刪除的分頁則會被清除)。
  • 遊戲程式碼依位址載入:SheetForgeDatabases.LoadAsync<FooDatabase>("Foo")
  • Addressables 群組資源已加入 gitignore,且可自我修復(缺少時會由匯入自動重新建立)。

Baseline——往返流程如何保留你的試算表

匯入時,每個分頁結構(標記列、欄位順序、註解、人工撰寫的文字)的標準化快照,會被儲存為 baseline。匯出時,則會把目前 SO 的數值代入 baseline 的結構中。

因此「試算表 → 匯入 → 匯出 → 試算表」這樣的往返流程,在結構上會 100% 保留你的試算表,並在語意上保留數值:

  • 1.01 是允許的,因為數值本身相同。
  • 浮點數會使用最短的往返格式。
  • 小數點永遠使用 .,不受地區設定影響。

哪些會被提交,哪些會被重新產生

產物政策
試算表(本機檔案)/Google 試算表真實來源。 提交/共享。
烘焙後的 Database SO(Assets/SheetForgeBaked已加入 gitignore 的依機器而異快取——透過執行匯入重新產生。
產生的程式碼(Assets/SheetForgeGenerated建議將其提交。 它是你專案自己的原始碼,位於 Assets/SheetForge 之外,因此重新安裝本產品不會刪除它;提交它代表新複製的儲存庫在任何人執行匯入之前就能編譯。其輸出具有確定性,因此隊友的匯入會產生完全相同的位元組。改以 gitignore 排除它同樣是有效的替代方案,下一次匯入會將其重新產生。早於這項預設值就存在的專案,會持續產生到 Assets/SheetForge/Runtime/Generated,直到該資料夾被清空為止——請參閱快速上手
Addressables SheetForge 群組資源已加入 gitignore,可自我修復。不要提交它首次建立時產生的那一行設定差異。
領域套件自己的 Generated 資料夾由該套件自行決定。 隨附的 SheetForge.PluginDemo 範例會提交其產生的程式碼,讓示範內容一經匯入即可立即編譯。
匯入設定資源由你自行管理;請將服務帳戶金鑰的路徑留在儲存庫之外(使用 SHEETFORGE_SHEETS_KEY 環境變數)。

無需修改的擴充方式

註冊合約能讓外掛以零 Core 修改的方式加入此管線:

  • 儲存格型別剖析器(包含 wrapper 型別)、領域驗證器、邊貢獻者;
  • 自訂結構標記、「建立試算表」範本、匯入來源提供者;
  • Data Studio 的畫布覆寫、程式碼註冊表、小工具、動作、儲存格小工具、色彩預設與 UI 字串。

Core 絕不會參照任何領域套件;這種單向相依關係由編譯器強制執行。權威清單——以及其確切數量——請見外掛開發

相關頁面