Free Documentation Template Icon Download Videos Support Blog

Overview

Meta Sheets is an Editor extension for Unity that converts google spreadsheets into type safe C# code. Setting up a spreadsheet is easy. Optional annotations are intuitive and enable some seriously powerful features.

You can access the data from any script

Once your project is running in the editor or on any platform you can reload the data straight from the spreadsheet and tweak values. For some great ideas visit the blog.


Features

  • Easy to setup and use
  • Automatically detects data types
  • Clever and optional annotation syntax
  • Extend your data with custom methods and code
  • Supports advanced types such as Color, Dates, Arrays or eNums
  • Reload at runtime and tweak values on existing builds

Download

For Meta Sheets there is a free version and a Pro version. The free version is very capable but doesn't support all object types and lacks a few advanced features. If you want to give Meta Sheets a try then the free version is a great start.

Meta Sheets Free Meta Sheets Pro
• 6 data Types • 18 data Types
• Reload at runtime
• Extend data with base classes
• Fully commented code
Get Free Get Pro

Support

Questions, feedback and issues can be raised at metasheets.helprace.com . You can also post your comments at the Unity forums.

MetaSheets comes with 5 sample projects that demonstrate basic and advanced features. Examples include: Basics, an Audio Manager, Reloading and text Translations.

The MetaSheets Blog will cover more example scripts in the future. Additional examples can also be requested via the support page.


Data Types

By default MetaSheets assumes that your data is stored as strings unless specify a type, extend it to a base class or the values all match a certain type.

Basic Types

The following types are supported both in the free and pro version of Meta Sheets.

Type Example Default Value Detection rules
string "" Last resort if nothing else could be detected.
int 0 Parsing as an integer succeeds.
float 0f parsing as a float succeeds.
bool false Parsing as a boolean succeeds. Valid boolean values are true, false, 1 and 0.
Vector2 Vector2.zero Parsing as float[] or int[] succeeds but the array length is 2.
Vector3 Vector3.zero Parsing as float[] or int[] succeeds but the array length is 3.

Pro Types

In addition of all the basic types the pro version of Meta Sheets supports these additional types.

Type Example Default Value Detection rules
eNum ERROR A series of string entries each of maximum length of 24 characters that have at least 2 duplicates all together and at least 1 unique duplicate. Items can not contain odd characters.
eNum[] new eNum[0] A series of individual string entries or comma separated entries each with a maximum length of 24 characters that have at least 2 duplicates altogether.
Color Color.Black A # character followed by 3 RGB or 4 ARGB values stored as hexadecimal values.
int[] new int[0] Parses as all comma separated integers without '.' characters succesfull.
float[] new float[0] Parsing as all comma separated floats succeeds.
bool[] new bool[0] A series of booleans separated by comma ','. Each parsing as an boolean successful. Valid boolean values are true, false, 1 or 0.
string[] new string[0] A series of strings separated by comma ',' of which each string does not contain the following characters: tab, newline, quotation signs.
Color[] new Color[0] Parses all comma separated #hexadecimal values successful. A single hexadecimal starts with a # character followed by either 6 or 8 characters of the hexadecimal character set.
Class null The header needs to start with any of the sheet names followed by any variable name. Any of the entered values need to start with the same sheet name followed by a '.' and a identifier of that referenced sheet.
Class[] new class[0] The same rules as the 'Class' type apply here except that everything is treated as an array. Each entered array value must contain the sheet class name reference followed by a '.' and an identifier of that referenced sheet.
DateTime DateTime.Today 3 digit pairs separated by / characters. Either as YYYY/MM/DD or DD/MM/YYYY order.
TimeSpan new TimeSpan(0,0,0) 2 or 3 pairs of integers below 60 separated by : characters. Expects either a hh:mm:ss or mm:ss order.


Documentation

This manual should get you started using Meta Sheets. The following part of the documentation applies to both the Free and Pro version of Meta Sheets. For Meta Sheets pro specific documentation scroll further down.

Setting up a Google sheet

  • Create a new google sheet and consider the following:
    1. The sheet name (tab name) describes the category.
    2. The first row is used to describe your variables.
    3. Starting with the second row each represents an object that Meta Sheets will parse against the properties of the first row.

  • Next select
    1. File
    2. Publish to the web...
    3. Choose the "Entire Document" and then press Publish. This will make the document readable from outside but keep your document unlisted from the web.

Generating Code

  • Open Meta Sheets from the Unity menu: Assets > Meta Sheets
  • Copy and paste the URL of the google document (make sure it is published), Meta Sheets should automatically extract the correct key.
  • Enter a class name, for example "Data"
  • Click Generate "Data.cs".

Tip: The class name determines how you access code later from your C# scripts. Essentially the class name will be your entry point to access all of the data.

How to access the data

When converting a spreadsheet into C# code the following translates into parts of the generated code

  1. Sheets (tabs) turn into classes each with a static singleton.
  2. Rows turn into objects; all objects together into an array.
  3. Columns turn into properties.

Tip: When your first column consists of strings Meta Sheets will create id accessors that you can access from code. Otherwise you have to access it as an array[] item or from within a foreach loop.

Inside your scripts you can then start typing the names of the sheets followed by their id's and then their properties. Like

{Data}.{sheet}.{id}.{property}

Apart from accessing data from their static variables you can also Access items as Array like list of items

//Static id Access
Debug.loop("Sfx of axe: "+Data.weapons.weapon_axe.sfx);
 
//Access as string ID
Debug.loop("Sfx of axe: "+Data.weapons["weapon_axe"].sfx);
 
//Access in a for i loop
for(int i=0; i < Data.weapons.Length; i++){
    Debug.Log("Sfx: "+Data.weapons[i].sfx);
}
 
//Access in a foreach loop
foreach(DataTypes.weapon weapon in Data.weapons){
    Debug.Log("Sfx: "+weapon.sfx);
}

Entering values

Most of the time you can name columns, rows and sheets however you want. In some cases however MetaSheets will automatically convert names to c# safe object names. This may happen when some of your identifiers contain unsafe characters such as /\\#-.?<> []{}() or are equal to unsafe keywords such as abstract, as, base, bool, break, byte, ...

For the values certain types of values expect a certain way of entering the values in the spreadsheet. Most of the time you write the values as if you would write them in code. In most cases Meta Sheets will automatically figure out how to convert your data. Should it fail however Meta Sheets or the compiler will tell you in detail what type of data was expected where.

A complete list of the supported object types and their syntax can be found at the Data Types section further below.

Ignoring elements

Empty rows are ignored when building or reloading sheet data in Meta Sheets. You can mark sheets, columns or rows to ignore in Meta Sheets by adding a // in front of their names.

Above: The item '// unkown' will be ignored as well as the property '//color'. You can also ignore entire tabs by adding '//' in front of the tab name:


Enforcing types

Meta Sheets can detect object types automatically if the majority of all values match a certain criteria. Sometimes however you might want to enforce a certain variable type. To enforce a specific variable type write the object type in front of the column variable name. The way you write this follows the same convention as you would do in C#.

Note that some object types are only supported in the pro version of Meta Sheets. A complete list of the supported object types and their syntax can be found at the Data Types section.

Below are a few example types that can be forced in your spreadsheet.



eNums

Meta Sheets automatically detects enums when a series of strings have at least 2 duplicates. You can however also enforce a eNum type by writing eNum in front of your column label. eNumerators can also be used as eNum[] arrays with comma seperated values.

Meta Sheets will automatically generate an eNum structure with all of the unique items found from your spreadsheet. All of the data types are stored in a special name space called {Data}Types where {Data} is the name of your data class in MetaSheets unless you extended to a base class..

//Comparing weapon type
if(Data.weapons.weapon_axe.type == DataTypes.weapons.eType.swing){
    Debug.Log("This weapon is of type 'swing'");
}
 
//Log type and material values
Debug.Log("Type: "+ Data.weapons.weapon_sword.type.ToString() );
Debug.Log("Materials: "+Data.weapons.weapon_axe.materials[0].ToString() );

Class references

Items from other sheets (tabs) can be referenced as Class types. This will store a reference to the generated MetaSheets object and it's properties. This type reference is type safe as there are no string or array references used.

The following example casts the type people for the variable who. As you can see a sheet by the name people actually exists and will be referenced here in the generated code.

Important: You can only reference Class items if the sheet or tab you reference uses string ID's in the first column. This can be the ID column for example.

In the above example the property "who" will be casted of the type "people" .

//Access a referenced object of type "people"
Debug.Log("Axe is owned by: "+Data.weapons.weapon_axe.who.id);

//A more detailed break down
DataTypes.people object = Data.weapons.weapon_axe.who;
Debug.Log("Id of 'who' object inside 'weapon_axe': "+ object.id);

Class[] array references

Apart from referencing just a single item you can also reference Class array items. Each item needs to come from the same sheet (tab) type.

In the script the property "who" will be cast as an array of the type "people"

//Determine length
Debug.Log("People count: "+Data.weapons.weapon_axe.who.Length);

//Access the first item
Debug.Log("First person: "+Data.weapons.weapon_axe.who[0]);

//Access in a for i loop
for(int i=0; i < Data.weapons.weapon_axe.who.Length; i++){
    Debug.Log("Person["+i+"] = "+Data.weapons.weapon_axe.who[i]);
}

//Access in a foreach loop
foreach(DataTypes.person person in Data.weapons.weapon_axe.who){
    Debug.Log("Person: "+person);
}

Important: Sometimes when referencing other sheet classes from other tabs it can cause the C# to return some null values. This is caused by a deterministic initialization order of static members inside C# and causes some values to have their default values e.g. null values.

This can be fixed by re-arranging the tabs in your sheet in a particular order and not referencing oneself. Tabs with referenced elements should go to the left followed by tabs that reference other previous tabs each after another sorted by their dependencies.

 

Base Classes

A base class is a class that Meta Sheets will extend on a particular generated sheet code. Just like in C# and other OOP languages: base classes allow you to extend Meta Sheets generated code from the base and add for example additional variables, methods, getters, settings and alike. 

Let's take this simple class for example as our base class

public class Base {
	public enum eGender {
		male,
		female
	}
    
	public string name;
	public int age;
	public eGender type;

	public void LogInfo(){
		Debug.Log(string.Format("name:{0}, age:{1}, gender:{2}", name, age, type.ToString()));
	}
}

By writing this {sheetName}:{baseClassName} for the sheet name we can tell MetaSheets to extend the data of that sheet on our base class.

All public variables that match between the base class and the spreadsheet will be used and referenced in the generated data class. Variables that can not be found in the base class will be added dynamically to the data class that Meta Sheets generates.

This technique allows to access any of the base class features directly from a MetaSheets data item including methods. For example:

//Access base class features
Data.users.user_john.LogInfo();

To get more ideas as to for what this is useful for head over to the Blog or have a look at the MetaSheets bundled examples.


Custom Namespace

Namespaces are optional and allow you to nest the generated data into a custom namespace by changing the title of your sheet to the following convention:

This will generate the sheet data in a namespace of 'myNameSpace'. The namespace element will go in front of the curly brackets and the title must include the '{' and '}' characters around the document title.

With a namespace you may need to include it to your code when accessing the data, for example:

//Importing the namespace to the header of your C# Document
using myNameSpace;
...
Debug.Log("Data: "+ Data.sheetName.Length );

//Accessing it without importing
Debug.Log("Data: "+ myNameSpace.Data.sheetName.Length );

Namespaces are useful when you want to name different sets of Data with the same name. By adding namespaces you can better organise more complex projects.

Reload at runtime

With the pro version of MetaSheets you can reload changes from the spreadsheet at runtime- even on your target platform like Android, iOs or the web player. 
Inside Meta Sheets Window make sure you enable the "Reload code" tick which will generate the runtime reload code inside your data class.

From within anywhere in your code you can then call your data Reload() method.

//Reload Data
Data.Reload();

You can also pass a System.Action() to get signal when the data has been loaded.

//Reload Data with a signal
Data.Reload(OnDataLoaded);
 
void OnDataLoaded(){
    Debug.Log("Data has been loaded");
}

Sometimes your spreadsheet might contain a lot of individual sheets. It is often faster to load just individual sheets instead. The same options are available when loading individual sheets.

//Reload individual sheets
Data.sheetA.Reload();
Data.sheetB.Reload();

It's not recommended to use the reload functionality for a production build of your project mainly because of two reasons: Your runtime could break because of altered spreadsheet data that is not compatible anymore and because a lot of users might hit your document that you published causing a lot of traffic on Google's free service.

Using a proxy server

Certain target platforms such as the Unity plugin or WebGL require cross domain permissions from the Google hosted domains which are not available. In order to still reload on these restricted platforms one can bypass the loading requests through a proxy server.

Meta Sheets provides an example php proxy script that you can host on your server (together with a valid crossdomain policy). Paste the proxy script URL in the Meta Sheets proxy URL field including the '?url=' argument to have all data to be loaded via the proxy.

Editor Scripts

A great way of using MetaSheets is by integrating it into other Editor scripts. You can even access the generated Data in Editor UI's and scripts to automate tasks, unit tests, build settings, etc.

To build a data class from an Editor script you can use the Build method which is part of the MetaSheets main class.

//Build a C# Class from code
MetaSheets.MetaSheets.Build("Data", "1OjHL4ZUSInfkV207WNKi1tlHHhqITjUSrdyHJrQpSrI", true);

Parameters

className The name of the C# Class name, e.g. "Data"
documentID The document ID of the spreadsheet.
addReloadCode
When true will add additional Reload capabilities to the Data code

{Data} Class

This is your entry point to the spreadsheet data. The name of the class is defined in the MetaSheets window under 'Class Name'.

Exposes

{Sheet}A static variable that returns the sheet data.
ReloadA static method that reloads the data at runtime. An optional System.Action call triggers when it finished loading.

Example Code

//Access the spreadsheet Data
Debug.Log(Data);

//Reload all sheets and log when done loading. The System.Action Parameter is optional
Data.Reload( ()=>{
  Debug.Log("Done loading all sheets");
});

{Sheet} Class

This class represents a particular sheet of the spreadsheet. It extends the IEnumerable and behaves just like an array or dictionary. Think of it as the sheet tab of your spreadsheet.

Exposes

updatedA System.DateTime object that reflects when this data was last changed.
labelsA string[] array with all of the {property} labels of the sheet.
LengthThe length of this sheet and how many items are stored in here.
this[string id]A bracket accessor to access elements of this sheet by the string id. Important: This is only compiled into the code when your first column of the sheet contains string values.
this[int index]A bracket accessor to access elements by their index.
ToArray()Returns an array of the {Sheet} elements.
Random()Returns a random item of the {Sheet}.
Reload()Reloads the particular sheet data at runtime. An optional System.Action call triggers when it finished loading.
ContainsKey(string key)Checks if a particular string key exists. Important: This is only compiled into the code when your first column of the sheet contains string values.
{item}Specific static items that are defined if the first column of the sheet consists of strings. Important: This is only compiled into the code when your first column of the sheet contains string values.

Example Code

//Basic info 
Debug.Log("Sheet1 length: " + Data.Sheet1.Length);
Debug.Log("Item types: " + Data.Sheet1[0].GetType() );
Debug.Log("ContainsKey('apple')? " + Data.Sheet1.ContainsKey("apple"));

//Accessing items
Debug.Log("Random item: " + Data.Sheet1.Random());
Debug.Log("First item: " + Data.Sheet1.ToArray().First());//using System.Linq
Debug.Log("Specific item: " + Data.Sheet1.apple);
Debug.Log("Array accessed item: " + Data.Sheet1[0]);
Debug.Log("Key accessed item: " + Data.Sheet1["apple"]);

//Foreach loop access
foreach(DataBasicsTypes.Sheet1 item in Data.Sheet1) {
  Debug.Log("Foreach: " + item.id);
}

//for i++ loop access
for (int i = 0; i < Data.Sheet1.Length; i++) {
  Debug.Log("for i++: ["+i+"] = "+Data.Sheet1[i]);
}

//Reload a specific sheet only
Data.Sheet1.Reload(()=>{
  Debug.Log("Done loading Sheet1");
});

//Access specific item
Debug.Log("Sheet1 item 'apple': "+Data.Sheet1.apple);

{Object} Class

This class represents a single object item from a sheet (e.g. a single row from a spreadsheet). With MetaSheets Pro you can extend this class to a custom base class.

Exposes

{variable}A particular variable of the sheet. These represent the column headers in your sheet. Where each column is reflected as its own variable of each row item.

Example Code

//Access a property 'age' from apple in Sheet1 of Data
Debug.Log("The age of the apple is: "+Data.Sheet1.apple.age);