By default, Unity only serializes public fields. How can I serialize private fields and custom types to show them in inspector?
1 Answer
The [SerializeField]
attribute instructs Unity to serialize the field regardless of the accesibility.
All three fields below gets serialized and shows up on inspector:
[SerializeField]
private int _foo;
[SerializeField]
protected int _bar;
[SerializeField]
internal int _baz;
Note that, in order to expose custom types in Inspector, you need to explicitly mark them with [System.Serializable]
attribute.
All Foo1
_foo2
Bar
_baz
_qax
gets serialized and shows up on inspector:
public Foo Foo1;
[SerializeField] private Foo _foo2;
[System.Serializable]
public class Foo
{
public int Bar;
[SerializeField] private int _baz;
[SerializeField] protected int _qax;
}
However, there are some restrictions on serializing:
- Only primitive types internal Unity types, and custom types that marked with
System.Serializable
can be serialized. - Custom generic types can't be serialized.
- Properties can't be serialized.
- Dictionaries, multi-dimensional arrays, and most of the complex collection types can't be serialized.
Workarounds on restrictions
Custom inspector scripts (aka Custom editors)
Nearly in all cases where Unity can't serialize something on itself, you can write an editor script to tell Unity how to show the type in Inspector. For more information about custom editors:
Video tutorial about Custom Inspectors
Unity documentation page about Custom Editors
Wrapper classes and "faking" the type
When Unity can't serialize a collection, you can create a custom class to fake the data structure of the type.
If we take Dictionary type for example, you can fake it with an array of a wrapper class:
The original:
public Dictionary<string, int> FoobarDictionary;
The fake:
public FakeEntry[] FakeFoobarDictionary;
[System.Serializable]
public class FakeEntry
{
public string Key;
public int Value;
}
And with some LINQ, you can basically get a similar behaviour:
//using System.Linq;
public int GetFooBarValue(string key)
{
try
{
return FakeFoobarDictionary.Single(a => a.Key == key).Value;
}
catch
{
throw new KeyNotFoundException("There is no entry that has the given key.");
}
}