Getting Started
Requirements
- Unity 6 (developed and tested on 6000.0.79f1, URP template).
- Addressables package (
com.unity.addressables) — required. Address loading is the runtime path, and theAssetRef@Grouptype needs Addressables.- Without the package the asset still compiles, because all Addressables-using code sits behind a
SHEETFORGE_ADDRESSABLESversion-define. - But the pipeline — import · export · push · authoring write-back — stays locked. Each entry point shows an install notice, and the Getting Started window guides the install.
- Without the package the asset still compiles, because all Addressables-using code sits behind a
Installing Addressables
- Primary path: when you import the asset from the Asset Store, the "Package Manager dependencies" prompt appears before compilation — choose Install and Addressables is installed alongside.
- Safety net: if you pressed Skip (or imported manually), the pipeline stays locked and the Getting Started window guides you to install from its Addressables status row. That window runs even without Addressables, because the Editor still compiles.
- The dependency-free
SheetForge.Setupbootstrap window also detects the missing package at editor load and shows a notice once per session. Because it has no dependencies, it keeps working even when other compile errors block the main assemblies.
- The dependency-free
- There is no one-click programmatic install: Asset Store submission rules restrict programmatic package installation, so the window guides you instead.
- The notice reflects the real install state. It explains that the product compiles but its features stay locked until the package is installed, and points you at the Getting Started window afterward. You can reopen it any time from Tools ▸ SheetForge ▸ Addressables Setup (this menu survives even if the main assemblies fail to compile for some other reason).
Upgrading from a previous version
A .unitypackage import adds and updates files but never deletes them. So a file that a newer version retired can linger in Assets/SheetForge, still referencing an API that no longer exists. Compilation breaks, and it looks like the upgrade broke your project. Two nets cover this:
- Automatic detection. At editor load, the dependency-free
SheetForge.Setupbootstrap checks for the paths this product has retired. If it finds any, it offers to delete them — listing every path in the dialog first and touching nothing until you approve. It lives in its own assembly precisely so it survives the compile errors it exists to fix. - Clean slate. For a guaranteed-clean upgrade, delete the existing
Assets/SheetForgefolder, import the new package, then run Run Import once to rebuild what the deletion took with it. Settings assets and baked SOs (Assets/SheetForgeBaked) live outside that folder and are untouched, and so is generated code once it sits at its default locationAssets/SheetForgeGenerated. If your project still generates into the older in-product location (Assets/SheetForge/Runtime/Generated), deleting the folder removes that code and the re-import writes it toAssets/SheetForgeGeneratedinstead. That is the supported way to move an existing project to the new location. What no re-import can rebuild is anything you put insideAssets/SheetForgeyourself — a settings asset saved there, your own plugin scripts, sheet files — so move that out first.
One boundary worth stating plainly: the automatic cleanup deletes SheetForge's own retired files, never yours. If your own plugin code implements a contract that has since been retired, it has to be ported by hand. In short:
- a per-tab graph builder (
IGraphShapeBuilder/GraphSpecBuilder) becomes the record canvas's augmenter (IRecordCanvasAugmenter/CanvasAugmentBuilder), which adds to the closure the canvas already built instead of building the whole picture; GraphModeis gone, since direction is now the canvas's own control;StudioGraphContext.ShapeId/ModeIdstill compile but each returns a constant, so anyAppliesTocomparison against them should simply be deleted;IAuthorableGraphShape.CreatableTabsis unchanged.
The full table of what each retired contract became is the Upgrade notes section of CHANGELOG.md in the source repository (the release package does not ship it). Retired members that still compile are marked [Obsolete] rather than removed, so an upgrade surfaces them as warnings instead of breaking the build.
The Getting Started window (start here)
Once Addressables is installed, a Getting Started window opens automatically once per editor session — on each Editor start, but not again after a domain reload. It keeps doing that for as long as its "Show this window when the Editor starts" toggle is on, which it is by default.
It is the recommended entry point. You can reopen it any time from Tools ▸ SheetForge ▸ Getting Started, and turn the auto-show off with that toggle at the bottom (the choice is stored per project and per user).
It gathers the whole first-run flow in one place:
- Status dashboard — a three-row traffic light: Addressables installed, an active import settings asset, and first import completed. Each row shows ✓ or ✗, and anything that still needs attention has an action button right next to it (New settings asset, or Run Import).
- Import settings — lists every
SheetForgeSettingsasset with a radio button to choose the active one, plus a New settings asset button and a Reveal button to locate each asset. - Examples — one click imports the Plugin Demo or Core Demo package.
- Start from a template — pick one of the two built-in ones, choose "from scratch" to define fields yourself, or use a plugin-registered template. "Use" opens the Data Studio's create panel pre-filled with it. This needs an active settings asset with a writable source; if you don't have one yet, the requirement is shown.
- The built-in ones are Item example, which uses core types only, and Enum definitions, which lays out an
@enumsheet. - The skill-demo tabs appear here only when a template plugin such as the Plugin Demo is present.
- The built-in ones are Item example, which uses core types only, and Enum definitions, which lays out an
- Run — Run Import (uses the active settings) and Open Data Studio.
- Open Full Guide — a link to this documentation site.
The sections below explain each step in detail; you can do everything from the window, or from the menus and the Project window as described.
Even faster — drag & drop. If you already have a folder of sheet files, open the Data Studio and drag that folder onto it — or a single .tsv/.csv/.xlsx file. It offers to create an import settings asset that reads from that folder and make it active, with no manual setup.
Opened with no active settings, the Studio shows a "Get started" panel with the same create / import-demo / Getting-Started buttons instead of an empty table.
Health check. At any point, open the Data Studio and pick ⋯ ▸ Health Check from the toolbar for a quick, no-network diagnosis. It reports ✓/✗ — each with a suggested fix — for:
- the active settings;
- whether the source is reachable (a local folder that exists, or a Google id + key path);
- whether an import baseline exists;
- whether the generated code, baked SOs, and addressables are up to date.
UI language. The first time you open a project, SheetForge sets its UI language from your Editor's system language (nine languages map; anything else stays English). It never overrides a language you already picked; change it any time in Preferences ▸ SheetForge (see Localization).
1. Choose an import settings asset
Create one from the Getting Started window's New settings asset button, or right-click in the Project window → Create ▸ SheetForge ▸ Import Settings (menu labels follow your language setting — see Localization).
You can keep several settings assets (for example, one per data source) and choose which is active. Menus, the Data Studio, and imports all use the active one. The choice is stored per project and per user — an EditorPrefs pointer, so no VCS churn and independent per teammate — and if the active asset is deleted the pointer self-heals.
With a single settings asset, your first import auto-selects it; no explicit choice is needed. When multiple exist, choose the active one in the Getting Started window or from the dropdown that appears in the Data Studio toolbar.
Configure the SheetForgeSettings asset:
| Field | Meaning |
|---|---|
| Source (dropdown) | Built-in LocalFile (folder of .tsv/.csv/.xlsx) or GoogleSheet — both are complete production paths. Custom plugin sources (DB/REST, etc.) appear here too if registered. Stored in sourceProviderId; when empty, the built-in LocalFile provider is the default. |
localFolderPath | LocalFile mode: the folder containing sheet files. Only the folder's immediate children are scanned. |
spreadsheetId | GoogleSheet mode: the target spreadsheet ID (service-account auth required for SheetsApi mode). |
bakeOutputFolder | Where baked Database SOs go. Default Assets/SheetForgeBaked. |
generatedCodeFolder | Where generated .cs files go. Default Assets/SheetForgeGenerated, deliberately outside Assets/SheetForge so reinstalling or moving the product never deletes your generated code. A project that already generates into the older in-product location (Assets/SheetForge/Runtime/Generated) keeps that location until it is empty; Upgrading from a previous version covers moving. Any folder works. If generated code references plugin types the folder's assembly cannot see, import automatically emits a companion .asmdef there to wire the references (the core runtime assembly stays clean). Note this is only the home for new tabs. A tab whose generated type already exists elsewhere (e.g. a plugin package's committed Generated) is regenerated in place at its existing location, and stale duplicates are cleaned up automatically with a console log. |
generatedNamespace | Namespace for generated types. Empty = SheetForge.Generated. Set a unique one (e.g. MyGame.Data) to isolate your generated types from other packages and the bundled example. |
exportFolderPath / exportFormat | Export destination and format (Tsv / Csv / Xlsx / MatchSource). |
The settings inspector shows only the fields relevant to the current source mode — Local mode hides the Google inputs; the gidMap appears only in Google ExportUrl mode.
2. Service-account key security (Google source)
Using a LocalFile source? Skip this section.
Using Google Sheets in SheetsApi mode requires a service-account JSON key. If you have never created one, Google Sheets Setup walks through the whole process step by step. Keep this key outside Assets/ and outside your repository — never commit it.
- Recommended: set the environment variable
SHEETFORGE_SHEETS_KEYto the absolute path of your key file. It takes precedence over the settings asset's key-path field, so each developer injects their local key without leaving any path in the repo. - If you must put a path in the settings field, point it outside the repo (e.g.
C:/keys/service-account.json). A key file underAssets/would leak into builds and commits.
3. Run your first import
Tools ▸ SheetForge ▸ Data Studio, then press ↓ Pull from source in the toolbar.
- The pipeline fetches → validates → (on success) generates code → bakes. Diagnostics are printed to the console as a human-friendly report in your language.
- The first import completes automatically in two internal stages. When a schema is new or changed, import writes the generated code, which triggers a compile/domain reload. It then automatically resumes the bake after the reload. One user action; no manual re-trigger. If compilation fails, the auto-resume safe-aborts (attempt cap 3) and leaves an actionable sentence in the console.
- Validation collects all diagnostics at import time (it never stops at the first error). If even one error exists, no output is produced (no partial assembly).
- Import auto-registers each tab's Database SO to the Addressables group
SheetForgeat the address"SheetForge/{tab}"— your game loads by that stable address (see Core Concepts).
4. Load data in your game
using SheetForge.Runtime;
using UnityEngine.ResourceManagement.AsyncOperations;
AsyncOperationHandle<DefinitionDatabase> handle = SheetForgeDatabases.LoadAsync("Items");
await handle.Task; // or coroutine yield / handle.WaitForCompletion()
if (handle.Status == AsyncOperationStatus.Succeeded)
{
DefinitionDatabase db = handle.Result;
// For strong typing: SheetForgeDatabases.LoadAsync<ItemsDatabase>("Items")
}
SheetForgeDatabases.Release(handle); // Addressables is ref-counted — release what you loadThe SheetForge.Runtime assembly is autoReferenced, so game code can use it without an asmdef reference.
Never reference a baked SO directly from a scene. Baked SOs are non-committed, per-machine caches — their GUIDs differ across machines and re-bakes, so a direct scene reference goes Missing on a teammate's machine. Address loading absorbs this by design.
5. Try the demo scenes
Two samples ship as selective import packages. The plugin sample SheetForge.PluginDemo (custom types, enums, validators, edges) and a plugin-free SheetForge.CoreDemo (core built-in types only) each include an "open and Play" demo scene.
Demo imports live in one place — the Getting Started window's Examples section — so there is no menu leaf for them.
- Plugin demo: press Import Plugin Demo in Getting Started, or double-click
Assets/SheetForge/Examples/SheetForgePluginDemo.unitypackage. Either restores it underAssets/SheetForge.PluginDemo/…. Scene:Demo/PluginDemo.unity(menu Tools ▸ SheetForge ▸ Open Plugin Demo Scene, added by the sample itself). It loads the example databases by address and shows a skill assembled from sheet data (fireball total damage = Damage 10 + DamageOverTime 3×3 = 19). - Core-only demo: press Import Core Demo in Getting Started, or double-click
Assets/SheetForge/Examples/SheetForgeCoreDemo.unitypackage. That restores it underAssets/SheetForge.CoreDemo/…. Scene:Demo/CoreDemo.unity(menu Tools ▸ SheetForge ▸ Open Core Demo Scene). It shows loadouts assembled from item references using core built-in types only. The demo also carries a localization sheet (ExampleStrings) whose keys the items reference throughLocRefcells — see Localization Sheets.
(These sample menus' leaf labels are English, as they sit outside the core localized-menu pipeline.)
Each demo package bundles a pre-configured settings asset. When you import a demo package, SheetForge auto-activates that bundled settings asset if you have no active settings of your own. If you already have one, it opens the Getting Started window to suggest switching instead of silently overwriting your choice. So the demo flow is simply: import the package → (settings auto-activated) → Run Import → Play — no manual settings creation.
A demo works only after running one import on your machine — the Addressables addresses it loads exist only after the import has run once (the Addressables group asset is a non-committed, self-healing cache). Before that, the demo scene shows a guidance message instead of failing.
To finish a demo (after importing the sample package above):
- Make sure the demo's bundled settings asset is active (the Getting Started window shows it, or the import auto-activated it). It uses source = LocalFile, local folder = the sample's
DemoSheetsfolder, and the defaultSheetForge.Generatednamespace so re-import regenerates the committed types in place. - No action needed for the plugin demo's script reference. The
ExampleEffectstab includes anAssetRef@Scriptsexample. The sample registersDemoScripts/special_effect.lua.txtunder the addressspecial_effectin aScriptsAddressables group by itself, idempotently, so the first import passes reference validation. Only if it logs a warning that it could not do so (a missing asset, for instance) do you need to add that entry by hand — or delete the row if you don't want the Addressables example. - Press ↓ Pull from source in Tools ▸ SheetForge ▸ Data Studio once (or the Run Import button in Getting Started), then open the demo scene and press Play.
6. Team workflow summary
- Baked SOs (
Assets/SheetForgeBaked) are a per-machine cache. Gitignore them, and after cloning each teammate runs Run Import once. - Generated code (
Assets/SheetForgeGenerated) is your project's own source, and committing it is the recommendation. A fresh clone then compiles before anyone has run an import, and schema changes show up in review. It is deterministic output, so a teammate's import produces the same bytes and creates no churn. Gitignoring it instead also works; the post-clone Run Import is then what restores compilation. - A pre-build freshness hook checks, per committed generated Database type, that (i) the baked SO exists, (ii) the schema fingerprint matches the baseline, and (iii) the Addressables registration exists. If anything fails, the build is aborted with an actionable sentence, so a clone/CI machine can never ship an empty cache silently.
Related pages
- Core Concepts — why the sheet is canonical and what the pipeline stages are
- Sheet Syntax — how to write your first sheet
- Sources, Export & Push — Google setup details
- FAQ & Troubleshooting — first-run issues