- Home /
List of Inherited abstract Objects assigned via Inspector
Hi, trying to tackle this little issue, hopefully the Unity inspector supports it.
Given these two sample classes:
public abstract class BaseClassA : MonoBehavior {
}
public class ClassA : BaseClassA {
}
public class ClassB : MonoBehavior {
public List<BaseClassA> Collection;
}
I am able to designate the list size in the inspector, but I can not attach (click and drag) the inherited ClassA to any of the elements in the list.
Any thoughts on this?
Edited by AlwaysSunny : to improve specificity.
I'm not positive, but this may be because the class is abstract. I don't think I've ever ran across a need to maintain a collection of "abstract objects". As I think on it, the concept makes less and less sense, but I also see why it seems like a reasonable request. Can someone back me up or make me look foolish? We might both learn something.
I dont understand why you would want to do this. Why not simply make the List of type ClassA?
ClassA is expected to have more information than BaseClassA so ClassA wont fit in to the model of BaseClassA but BaseClassA would fit into the model of a ClassA, if it could be instantiated.
I think an abstract class can not be instantiated but only derived from and overridden.
I could be way off here. Forgive my poor ter$$anonymous$$ology.
This is really a program$$anonymous$$g question, not a Unity Question.
Sorry, it crossed my $$anonymous$$d to clarify on this. The abstract class is inherited by multiple child classes. Simple case of good old polymorphism :-).
To give you the exact context, I have a BaseEvent class, and several, such as $$anonymous$$oveCameraEvent, RespawnEnemyEvent derive from it.
@AlwaysSunny - I did try non abstract base class, but alas no effect.
@$$anonymous$$eat5000 - The issue is pretty heavy into program$$anonymous$$g, but the issue lies with Unity and whether it will allow the inspector to assign scripts(classes) to a collection.
Last note as I lay here, would creating a custom editor sound like the only solution (if anyone has ran across this)?
I know I've made lists containing monobehaviors and derivatives thereof without additional editor scripting. I'm absolutely, positively, somewhat... kinda-sorta sure...
But never a list of abstracts, that's the part that seems weird to my eye. You could give it a shot with the custom inspector, just to see what happens.
@AlwaysSunny you say:
I don't think I've ever ran across a need to maintain a collection of "abstract objects"
Consider an abstract class Animal which you make abstract because the concept of animal is itself abstract, you don't find animals out there, you find Dog or Cat that are Animal. So your Dog and Cat inherit from Animal so that they belong to the same "family". Consider you have an abstract Sleep method (or virtual for that matter, just that abstract imposes an implementation) in Animal because this is inherent to any animal to sleep, here is what could happen:
List<Animal>list = new List<Animal>();
list.Add(new Cat());
list.Add(new Dog());
foreach(Animal animal in list)
{
animal.Sleep();
}
Note that this is pretty much the same as having a ISleep interface which would be even better as it would simplify the hierrachy BUT, you cannot use interfaces in the inspector since they are not $$anonymous$$onoBehaviour. Abstract classes allow the slot to show in the inspector. ($$anonymous$$aybe some custom inspector would fix that I guess)
Answer by Bunny83 · Mar 12, 2015 at 03:52 AM
Just tested it again in the newest version of Unity (but i was quite sure that it will still work) and it worked just fine. Maybe you tried to drag a script file directly to your "Collection" list which of course isn't possible.
When you drag a script file you actually drag a MonoScript which represents a class and not an instance of that class. You can "drop" such a class onto a GameObject to create an instance of it (which will be attached to that GameObject).
Your "Collection" list actually holds references to instances of classes which are derived from BaseClassA. So you can only drag and drop instances to that list. To do that you have several options:
If your instance of ClassA is attached to another GameObject in the scene, just grab the GameObject in the hierarchy where a ClassA script is attached to and drag it into a slot of your "Collection" list.
If your instance of ClassA is attached to the same GameObject as your ClassB, you can grab the header bar of the script component in the inspector and drag it onto your list slot.
If you have multiple instances of a compatible class (anything derived from BaseClassA) on the same GameObject, you have to use another inspector window and lock one to your object which holds ClassB so it stays visible. Now simply select the GameObject which has the ClassA instances attached and again grab the header bar in the inspector of the instance you want to put on the list and drag it over into the list of ClassB in the other Inspector window. (To open another inspector, just click any window menu at the top right and select "Add Tab" -> "Inspector". You might want to arrange the two inspectors next to each other so you'll see both). To lock an inspector to the current selection, just press the "pad lock" icon next to the window menu button.
@Bunny83 - I do understand the issue of instantiation. Digging around today I did find a Unity class you can inherit from specifically for not having to attach to a gameobject: ScriptableObject. I'm still not familiar enough with Unity to know how the inspector assignment handles references though, so may not be applicable to this issue. And FYI I did try this for my base class, but still no luck.
So let me in turn ask, is this not a feasible approach to handle a list of many scripts like how I'm using it as a collection of events to fire off? I know I could instantiate them through the start method of my Event$$anonymous$$anager(ClassB in my example, which is attached to an object). I was just hoping to make use of the nice user interface
@Neovivacity: You seem to be confused or at least not clear about how you want to use those "items" in your list. Again a script represents a class. You can't do any thing with a class beside creating an instance of it. $$anonymous$$onoBehaviours can only be created with AddComponent and ScriptableObjects only with ScriptableObject.Create.
Like i said in my comment above, C# doesn't have something like a reference to a class. From your comments above it looks like you want to store "class references" (which doesn't exist) in your list so you can create the appropriate class when you need it. If that's the case you might want to go the "list-of-strings" variant to create the instances at runtime when you need them.
Another way is to attach all instances at edit time to a GameObject and store all those instances in your list (That's what i actually described in my answer).
ScriptableObjects aren't really useful in this case. They are meant to be created as assets at edit time to store serialized data in an asset without the need of a GameObject. At runtime you would usually use plain C# classes (not derived from $$anonymous$$onoBehaviour or ScriptableObject). "normal" classes however aren't serialized. So here we are again at the point where it depends on what exactly you want to achieve...
@Bunny83 No issue with the C# side of things (I have quite a career in C#) :-). $$anonymous$$y only weak point is learning Unity and how it deals with its scripts, more so I fully understand the issue with trying to attach a class vs and instantiated object ( I've taught on the topic, lol).
$$anonymous$$y aim is to get a solution from a seasoned Unity developer, not just clarification on this problem.
Never the less our dialog has sparked an idea. I'll work on it tomorrow when I have time and post back.
Thanks everyone so far! Great ideas everywhere.
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Custom list-item name 0 Answers
Change a Class in the inspector 1 Answer
Inspector issue 1 Answer