How do I use "helper classes" in C# and have them show up in the Inspector?

I may have the terminology wrong, so I apologise, but here’s an example of what I mean.

In javascript I discovered you can do this:

class Foo {    
	var whatsit = 0;    
}

class Bar {    
	var thingus = "two";    
}

var stuff = "nonsense";
var foo:Foo;    
var bar:Bar;

If you attach that to an object and look at it in the inspector, you’ll see the script, and under it you’ll have your Stuff variable with “nonsense” in it. Then there will be a collapsible arrow for Foo and Bar with editable whatsit and dingus elements inside them.

I’m trying to do the same thing in C# but seem to be confusing myself on how this structure works. I seem to recall reading that every object in JavaScript inherits from MonoBehaviour, so I’ve tried to make my side classes do that as well, but while they show up in the inspector they don’t have anything in them.

using UnityEngine;
using System.Collections;

public class Test2: MonoBehaviour {
	public string stuff = "nonsense";
	public Foo foo;
	public Bar bar;

	void Awake(){
		foo = gameObject.AddComponent<Foo>();
		bar = gameObject.AddComponent<Bar>();
	}
}

public class Foo: MonoBehaviour {
	public int whatsit = 0;
}

public class Bar: MonoBehaviour{
	public string thingus = "two";
}

This results in my script showing up on the game object as before, but the Foo and Bar elements are set to “none (Foo)” and “none (Bar)” respectively. I tried doing an “AddComponent” in Awake and Start, but those are obviously not being called in the editor, only during runtime. trying to assign it when I declare the members doesn’t work because they’re not static members so GameObject.AddComponent won’t work.

Can anyone shed some light on this?

Thanks in advance.

The problem here is that you are treating these classes as MonoBehaviours- they really don’t need to be that, there’s a much simpler way of managing it (which, btw, is basically how the JS version worked).

public class Test2: MonoBehaviour {
    public string stuff = "nonsense";
    public Foo foo;
    public Bar bar;
}

[System.Serializable]
public class Foo {
    public int whatsit = 0;
}

[System.Serializable]
public class Bar {
    public string thingus = "two";
}

The [System.Serializable] tag is what tells it to make those little dropdown menus. If they derive from MonoBehaviour, it’ll assume that you want to treat them as references to components on other scripts (obviously not what you want to do here).