2
\$\begingroup\$

By default, Unity only serializes public fields. How can I serialize private fields and custom types to show them in inspector?

\$\endgroup\$
5
\$\begingroup\$

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.");
    }
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.