- Home /
ScriptableObject Method Overloading?
Let's say that I have a database of spells/abilities in my game, and they all share a handful of standard fields (cooldown, cast time, mana cost, etc), but each have very custom behaviour (crowd control, projectile damage, AoE, etc). Ideally, I would like to have these spells show up in the asset list so that I can click on them and edit those common fields via the inspector, and have the custom behaviour defined in script.
I can use ScriptableObject to have the spell show up in the project and be editable and stuff, but I can't figure out how best to go about defining the custom behaviour. The best solution I can think of is to have, say, a Spell class derived from ScriptableObject which has a public SpellBehaviour field, and that SpellBehaviour would point at the behaviour for the spell.
I feel like I should be able to simply overload the ScriptableObject and some of its methods to define the behaviour... But I don't think that's possible! Does this sound like an appropriate way to do what I'm trying to do?
I know this is a very old post. But i ran into the same problem and since this post hasn't been answered i thought it would be ok to revive it. Can anyone share some thoughts about the idea described above?
I already tried many aproaches where neither worked. for example i tried adding a public object field (dragged the scriptableobject derived behaviour in)and casted that to my SpellScript class to access its overridden Use() but that didnt work. (I'm not a professional programmer so the above may sound like gibberish) Thank you in advance.
Answer by Bunny83 · Dec 05, 2016 at 01:30 AM
Since we just have another very very old question that got bumped, here's the answer ^^.
First of all you have to be more careful with the terms. Overloading and overriding are two completely different things. What you want is overriding and polymorphism. There are generally 3 ways how you can define a method that can be overridden:
Make a base class that has a virtual method
Make an abstract base class that has an abstract method
Define an interface and let another class implement that interface.
For ScriptableObjects that should be assignable in the inspector only the first two options apply. Generally you can use interfaces in Unity, but interfaces can't be serialized by Unity so they can't be assigned in the inspector.
public class MyBaseClass : ScriptableObject
{
public string baseString;
public virtual void Use()
{
Debug.Log("MyBaseClass-->Use()");
}
}
public class SomeDerivedClass1 : MyBaseClass
{
public override void Use()
{
Debug.Log("SomeDerivedClass1-->Use()");
//base.Use(); // optionally call the base method that we have just overridden
}
}
Somewhere else you can declare a variable of type MyBaseClass and assign a "SomeDerivedClass1" instance:
public MyBaseClass behaviour; // can be assigned in the inspector
// [ ... ]
behaviour.Use();
Now when you call behaviour.Use(); it will print "SomeDerivedClass1-->Use()"
since we assigned a SomeDerivedClass1 instance.
Another way is to make out "MyBaseClass" class abstract like this:
public abstract class MyBaseClass : ScriptableObject
{
public string baseString;
public abstract void Use();
}
The derived class wouldn't need to be changed at all. The differences are:
abstract methods do not and can not have a body.
a class that has at least one abstract method need to be abstract itself.
abstract classes can't be instantiated.
In order to be no longer abstract, a derived class is forced to implement a body for all abstract methods.
So abstract base classes have the advantage that you can't create an instance of the base class and it ensures that a derived class will implement your method.
So if you want to specify an "interface" that you're going to use but don't have any generic code for it, use an abstract method. If you instead want to specify an interface that has some generic code and a derived class might want to override the default behaviour but isn't forced to, use a virtual method in the base class.
How Do you assing "SomeDerivedClass1" to behaviour variable ?
I'm not sure what you mean. When you have created an instance / asset of your concrete class, you can simply drag it onto the "behaviour" field. Keep in $$anonymous$$d that ScriptableObjects have the same limitations as $$anonymous$$onoBehaviours. That means each concrete ScriptableObject class have to be in a seperate file and the file name has to match the class name.