Modifying lists of inherited classes without adding a large number of Components possible?

Problem:
For the AI system I’m building, there are several abstract classes: Entity, Task, Action. All useable class objects inherit from these three. A child class of Entity (ex: CapsuleEntity) will have a list of Task child classes. Each task in that list will have a list of Action child classes.

In the inspector for a CapsuleEntity class I have a list of Tasks. When I drag a Task child class from the Project directory to the inspector list, it denies it. I am unable to add tasks to the tasks list, and therefore unable to add Action child classes the each task child class in the Task array. If I add tasks as components, and then add them to the list, everything’s fine.

Goal:
To add task and action children classes to their respective lists via inspector, without flooding the object with dozens of components. The overall idea is to easily build up these lists in the inspector and allow for Tasks / Actions to be added or removed during runtime. Below is a super simple example:

CapsuleEntity (script component)

  • Tasks (list)

  • DeliverSomething(Task)

  • MoveTo (Action)

  • DoSomething (Action)

  • AnotherTask (Task)

  • WaitFor (Action)

  • MoveTo (Action)

  • DoThing (Action)

Is there a smarter, more efficient means of easily concocting behavior within an inspector?

Aside: I’m writing my own AI system because I’d like to have a utility framework directing BTs based on priority and cost.

So… if I’m getting this you want to add your abstract classes to your Task inheriting classes List<> objects without actually making them a component in the game?

That is not possible. That’s like trying to “have ones cake and eat it too” as it were. For a class to exist in the game, you need an instance ie. a component. It must exist in memory when the game is running. You could call yourTaskListElement = gameObject.AddComponent<Task>(); within Start() to add it automatically when the game starts, and assign each yourTaskListElement to your list. It would work just fine. As for adding those classes to your list in the inspector, its either create a bunch of components in the inspector on the gameobjects, or automatically spawn them in your Start() method. Component clutter is not a huge deal either…

Of course its possible.

I’m implementing my own AI System that has most of the AI system held in ScriptableObject Assets and then an AI Brain component that simply refers to the AI System to use. The entire workflow is pretty similar to Unity’s own Mecanim System. so theres only one component placed on the GameObject, while all the details is left in the referenced AI System.

I built a saving system that can save specialized components on prefabs. Originally I was manually populating my AI task lists on start. Saving, and then removing that logic from start. Next time I loaded the game it would load the appropriate scripts based on a json file. It is tedious and severely prone to human error.

I’ve been looking into scriptable objects and they seem difficult to get polymorphic stuff serializing correctly. Is it possible to use Scriptable Objects to create an inspector-editable list of tasks? The way I intend to use the abstract Task and Action is by overriding. From what I saw it looked like a scriptable object version of actions and tasks lists would be only allow for modifying class fields.

On the contrary, its Custom classes that have that difficulty. sure you can make your custom class polymorphic, but you can’t have it serialized in the inspector. You can’t serialize an abstract type in the inspector as a concrete type. but you can serialize an abstract field reference. ScriptableObjects derive from UnityEngine.Object (like most things in unity: Monobehaviours, Textures, etc) thus you can set it to a field in the inspector. this way you have it so that you just reference the task abstractly, and then have that concrete type serialized someplace else.

ScriptableObjects are still classes like any other, so they still function much of the same way. You can make them abstract, have them implement interfaces, and use Virtual|Override modifiers just fine.

There are some drawbacks to ScriptableObjects, certain things you will have to work around (for example making prefabs with in-scene instances or serializing to file). but as far as Polymorphism goes ScriptableObjects work just fine.

I’m starting to understand. Just found Richard ‘superpig’ Fine’s Unite 2016 video about scriptable objects.

So it sounds like:
my abstract Action : ScriptableObject can be the base for many actions, for example: MoveTo, Chop, WaitFor, PickUp.
my abstract Task : ScriptableObject can be the base class for many tasks, for example: FellTimber. FellTimber could support logic for controlling its Actions List (populated by my example Actions).

I could then drag and drop FellTimber into my Entity’s Tasks list, and that task would preserve its list of Actions?

I plan on creating a prerequisite concept for my task logic. Using scriptable objects, could I simply have a task subclass reference another task subclass and any Entity could run it, so long as I pass the subclasses a reference to said Entity? For example TellTimber could have a prerequisite of ‘Axe Equipped’, which on fail would run the task FindAxe?

I don’t think scriptable objects are a viable solution for what I want, and I’m not sure there’s such a thing in Unity.
I like that scriptable objects allow me to to create lists of subclasses within the inspector. Perfect!
What I don’t like is scriptable objects of the same subclass will share the same variable. Example: I can’t have 3 TestAction objects in a list of Actions, and then change their individual State fields – by script or inspector.

Any way to get around this setback? Any ScriptableMonoBeObject base class hidden somewhere?

typically you would create an instance on a per action basis through editor scripting, set it to field and then add the instance to the main asset via AssetDatabase.

Mecanim is very similar in this regard. an Animator Controller is a scriptableObject asset that holds a list of ScriptableObjects (the animation states) which are created and merged into the Controller. then the Animator Component holds the state and passes itself to the animator controller to run. Each animaiton state is a ScriptableObject and they each have their own settings.