BakingSheet
Easy datasheet management for C# and Unity. Supports Excel, Google Sheet, JSON and CSV format.
Install / Use
/learn @cathei/BakingSheetREADME
BakingSheet 🍞
Easy datasheet management for C# and Unity. Supports Excel, Google Sheet, JSON and CSV format. It has been used for several mobile games that released on Google Play and AppStore.
Table of Contents
- Concept
- Features
- Install
- Contribution
- Usages
- First Step
- Supported Column Type
- Converters
- Save and Load Converted Datasheet
- Accessing Row
- Using List Column
- Using Dictionary Column
- Using Nested Type Column
- Using Row Array
- Using Cross-Sheet Reference
- Using Non-String Column as Id
- Using Post Load Hook
- Using AssetPostProcessor to Automate Converting
- About AOT Code Stripping (Unity)
- Optional Script Defining Symbols (Unity)
Concept
Throughout all stage of game development, you'll need to deal with various data. Characters, stats, stages, currencies and so on! If you're using Unity, scriptable object and inspector is not good enough for mass edition and lacks powerful features like functions or fill up. With BakingSheet your designers can use existing spreadsheet editor, while you, the programmer, can directly use C# object without messy parsing logics or code generations.
Let's say your team is making a RPG game. Your game has 100 characters and 10 stats for each character. If your team use Unity's scriptable object, designers will have to spend lots of time adding and editing from Unity inspector. And after setup what if you need mass edit, like to double ATK stat of all characters? Will you go through all characters with Unity inspector, or make Editor script for every time mass edit is required? With BakingSheet, designers can work easily with spreadsheet functions and fill ups without programmer help!

BakingSheet's core concept is controlling datasheet schema from C# code, make things flexible while supporting multiple sources like Excel files or Google sheets. You can think it as datasheet version of ORM. Also, you won't have to include source Excel files or parsing libraries for production builds. BakingSheet supports JSON serialization by default, you can ship your build with JSON or your custom format.
BakingSheet's basic workflow is like this:
- Programmers make C# schema that represents Datasheet. (They can provide sample Excel files or Google Sheet with headers.)
- Designers fill up the Datasheet, using any powerful functions and features of spreadsheet.
- Edit-time script converts Datasheet to JSON (or any custom format) with your C# schema and validates data.
- Runtime script reads from JSON (or any custom format) with your C# schema.
- Your business logic directly uses C# instance of your schema.
- Profit!
Don't trust me that it's better than using ScriptableObject? You might change your mind if you see how famous SuperCell ships their games with CSV, like Clash Royale or Brawl Stars. Though of course, their games aren't made with Unity, still a very good example to show how you can utilize spreadsheet!

Features
- Easy-to-use Datasheet management.
- Define schema as C# classes - no messy metadata on your datasheet.
- Supports importing from Excel, Google sheet, CSV and JSON.
- Supports exporting to CSV and JSON.
- Supports .NET platforms and all Unity platforms.
- Powerful Cross-sheet reference feature.
- Referencing Asset data with AssetPath.
- Customizable value converter.
- Customizable data verification.
- Partial sheet import.
Install
For C# projects or server, download with NuGet.
For Unity projects, add git package from Package Manager.
https://github.com/cathei/BakingSheet.git?path=UnityProject/Packages/com.cathei.bakingsheet#v4.1.3
Or install it via OpenUPM.
openupm add com.cathei.bakingsheet
Sample .unitypackage is available in releases. (Main package should be installed first.)
If you are planning to use StreamingAssets folder on Android, install BetterStreamingAssets as well.
Need help?
Before you start, we want to mention that if you have problem or need help, you can always ask directly on Discord Channel!
Contribution
We appreciate any contribution. Please create issue for bugs or feature requests. Any contribution to feature, test case, or documentation through pull requests are welcome! Any blog posts, articles, shares about this project will be greatful!
First Step
BakingSheet manages datasheet schema as C# code. Sheet class represents a table and SheetRow class represents a record. Below is example content of file Consumables page in MySheets.xlsx. Also, any column starts with $ will be considered as comment and ignored.

| Id | Name | Price | $Comment | |------------|-------------------|-------|------------| | LVUP_001 | Warrior's Shield | 10000 | Warrior Lv up material | | LVUP_002 | Mage's Staff | 10000 | Mage Lv up material | | LVUP_003 | Assassin's Dagger | 10000 | Assassin Lv up material | | POTION_001 | Health Potion | 30 | Heal 20 Hp | | POTION_002 | Mana Potion | 50 | Heal 20 Mp |
</details>Code below is corresponding BakingSheet class.
public class ConsumableSheet : Sheet<ConsumableSheet.Row>
{
public class Row : SheetRow
{
// use name of matching column
public string Name { get; private set; }
public int Price { get; private set; }
}
}
You can see there are two classes, ConsumableSheet and ConsumableSheet.Row. Each represents a page of sheet and a single row. ConsumableSheet is surrounding Row class (It is not forced but recommended convention). Important part is they will inherit from Sheet<TRow> and SheetRow.
Id column is mandatory, so it is already defined in base SheetRow class. Id is string by default, but you can change type. See this section to use non-string type for Id.
To represent collection of sheets, a document, let's create SheetContainer class inherits from SheetContainerBase.
public class SheetContainer : SheetContainerBase
{
public SheetContainer(Microsoft.Extensions.Logging.ILogger logger) : base(logger) {}
// property name matches with corresponding sheet name
// for .xlsx or google sheet, **property name matches with the name of sheet tab in workbook**
// for .csv or .json, **property name matches with the name of file**
public ConsumableSheet Consumables { get; private set; }
// add other sheets as you extend your project
public CharacterSheet Characters { get; private set; }
}
You can add as many sheets you want as properties of your SheetContainer. This class is designed to be "fat", means single SheetContainer should contain all your sheets unless there is specific reason to partition your sheets. For example when you want to deploy some Sheet only exclusive to server program, you might want to partition ServerSheetContainer and ClientSheetContainer.
Supported Column Type
string- Numeric primitive types (
int,long,float,double, and so on) bool("TRUE" or "FALSE")- Custom
enumtypes DateTimeandTimeSpan- Cross-sheet reference (
Sheet<>.Reference) - Nullable for any other supported value type (for example
int?) List<>andDictionary<,>- Custom
structandclassas nested column - Custom type converted with ValueConverter
Note
When usingJsonConverter,enumis serialized asstringby default so you won't have issue when reordering them.
Converters
Converters are simple implementation import/export records from datasheet sources. These come as separated library, as it's user's decision to select datasheet source. User can have converting process, to convert datasheet to other format ahead of time and not include heavy converters in production applications.
BakingSheet
