核心概念
試算表是唯一真實來源
你的資料只會有一種權威形式:試算表。其他一切都是由此衍生而來:
- IR(不可變的定義)是試算表經過驗證、組裝後的形式。
- 產生的 C# 類別是 IR 結構描述的強型別化呈現。
- 烘焙後的 ScriptableObject 是 IR 數值的可載入呈現——是一個查詢用快取,絕不是獨立的真實來源。
所有修改都必須透過試算表進行,並通過重新匯入的驗證後才會生效。直接編輯烘焙後的 SO 會製造出第二個真實來源,並繞過驗證——本產品刻意不將其支援為一種工作流程。(檢閱器中的「測試編輯」切換開關是為了暫時性的執行期實驗而存在;它絕不會被寫回,且重新匯入會將其清除。)
為什麼這很重要:把 SO 當成真實來源的專案,最終會出現未經驗證的資料逐漸偏離試算表、且無法調解的情況。在這裡,調解是結構性的——永遠從試算表重新產生。
IR——不可變、經過驗證的組裝結果
IR 是驗證所產生的結果。針對每個分頁,都會產生一個 SheetTable(結構描述 + 記錄),其儲存格已是具型別的值(int、float、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 中。
自動匯入鏈
當結構描述是新的或有變動時,一次匯入在內部會執行:
- 寫入產生的程式碼 → Unity 進行編譯 → 網域重新載入。
- 重新載入之後,此流程鏈會自行接續並完成烘焙。
你完全不需要手動重新觸發任何動作。如果編譯失敗(例如你的遊戲程式碼參照了一個剛被重新命名變更過的欄位),此流程鏈會安全中止,並在 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.0↔1是允許的,因為數值本身相同。- 浮點數會使用最短的往返格式。
- 小數點永遠使用
.,不受地區設定影響。
哪些會被提交,哪些會被重新產生
| 產物 | 政策 |
|---|---|
| 試算表(本機檔案)/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 絕不會參照任何領域套件;這種單向相依關係由編譯器強制執行。權威清單——以及其確切數量——請見外掛開發。
相關頁面
- 試算表語法——剖析器所讀取的標記與型別文法
- Data Studio——建立在此模型之上的編寫功能
- 來源、匯出與推送——往返流程的運作機制
- 編寫核心——編寫視窗底層的引擎