I am using Unity 5.4.2f2 Personal, and I have written a C# script similar to the following:
using UnityEngine;
using System;
public class Outer : MonoBehaviour {
// Some public outer fields
public class Inner : MonoBehaviour {
// Some public inner fields
}
}
I would like to be able to attach both Outer
and Inner
to GameObjects in my scene. Unfortunately, Inner
does not show up as an available script in the Unity Inspector, even if I add [Serializable]
to it. I know a lot of people will probably say there's something wrong with my setup if I'm trying to make a nested class visible to the outside world, but for the sake of this question, I just want to know if this can be done. I.e., is there any way to make nested classes usable as Unity components?
This answer is wrong!
At least it is only semi-true:
Okey, yes, it is true if your goal is to use and add this component via the Inspector's Add Component button, then NO it needs to sit in an individual script file with matching class name!
However, if you only add that component on runtime via script, then YES you actually can do that!
Unity itself does it e.g. in the Dropdown
component (excerpt from the source code decompiled with Rider)
public class Dropdown : Selectable, IPointerClickHandler, ISubmitHandler, ICancelHandler { protected internal class DropdownItem : MonoBehaviour, IPointerEnterHandler, ICancelHandler { ... } ... }
(Selectable
inherits from UIBehaviour
which inherits from MonoBehaviour
)
Which on runtime later looks like this in the Inspector due to this nesting
but is definitely possible!
To prove this you can easily do the same thing e.g.
public class TEST : MonoBehaviour
{
private class NESTED : MonoBehaviour
{
[SerializeField] private int someInt;
[SerializeField] private Transform someReference;
}
[ContextMenu("Add NESTED component")]
private void AddNested()
{
gameObject.AddComponent<NESTED>();
}
}
so as you can see even on edit time outside of playmode I can simply add this "hidden" component via the context menu
and it is still serialized and also still there after closing and reloading the scene: