- Home /
Polymorphic Scriptable Object
Everyone says ScriptableObjects can be used for inheritance.
1) I create the scriptable object with Factory: https://github.com/liortal53/ScriptableObjectFactory/tree/master/Assets/Editor
The asset is successfully saved on project.
2) I assign the scriptable object to my monobehavior.
3) Everything works fine.
4) I hit play mode.
5) Everything works fine.
6) i exit play mode.
7) Everything works fine.
8) i switch to another scene or close unity editor with X button at top right.
9) Scriptable objects get the message :
"The associated scripts can not be loaded ..."
And monobehavior link shows : None (MyClass)
I am frustrated, why do my scriptable objects go missing?
Ps. I am not willing to remove OOP concepts, i rather switch to another game engine.
Edit / Progress: Still havent solved the problem but ...
If in step 1 i use attribute [CreateAssetMenu], The asset is still saved in project like before. However the problem in step 9 gets fixed The monobehavior keeps the correct links to those assets and works perfectly. But now occurs problem 10.
10) Unrefered scriptableobjects created by [CreateAssetMenu] become missing, cannot be used by the monobehavior, they still consume disk space in my project.
So to conclude every scriptableobject created by [CreateAssetMenu] is "Safe" if refered by another monobehavior, but those unrefered get deleted, even thought it persists in the projects and takes up space.
Code:
[Serializable]
public class MyCameraType : ScriptableObject
{
public virtual void Init(MonoBehaviour mono) {}
}
[Serializable]
public class TopDownCamera : MyCameraType
{
public override void Init(MonoBehaviour mono)
{
Transform camera = Camera.main.transform;
camera.eulerAngles = new Vector3(90, 0, 0);
camera.position = new Vector3(0, 30, 0);
}
}
[Serializable]
public class ThirdPersonCamera : MyCameraType
{
public override void Init(MonoBehaviour mono)
{
Transform camera = Camera.main.transform;
camera.eulerAngles = new Vector3(0, 0, 0);
camera.position = new Vector3(0, 10, -20);
}
}
Edit: Revision 1: Applied Bunny83 code changes. Problem Still Persists.
Edit: Solution: Placing each script in a seperate file, fixed the problem.
Answer by Bunny83 · Nov 04, 2016 at 09:18 PM
I doubt that this is actually related to inheritance. Apart from your lost reference problem your "Init" method is not declared as virtual and not overridden in the derived classes, so all your OOP is pointless because you actually "hide" the Init method.
Assigning a concrete instance to a base class variable (of type MyCameraType) should store the reference just fine, however calling Init on the base class won't call the derived Init as it's not a virtual method. I'm not sure if that's just a typo here on UA or if this is your actual code.
Also ScriptableObjects don't need to be marked as "Serializable" as they are always serializable. In your case it would make more sense to make your Init method inside your MyCameraType class abstract. Abstract methods are also virtual but don't have a body themselfs and require a derived class to override it. Abstract classes also can't be instantiated.
public abstract class MyCameraType : ScriptableObject
{
public abstract void Init(MonoBehaviour mono) {}
}
public class TopDownCamera : MyCameraType
{
public override void Init(MonoBehaviour mono)
{
Transform camera = Camera.main.transform;
camera.eulerAngles = new Vector3(90, 0, 0);
camera.position = new Vector3(0, 30, 0);
}
}
you are right, i forgot to add virtual and override, thinking c# behaved as in java.
i had it as abstract class at first, but after seeing those missing errors, i decided to try as concrete class. The problems werent fixed.
So with your solution, unity keeps missing unrefered ScriptableObjects.
Answer by xarismax · Nov 04, 2016 at 10:25 PM
Turns out, the reason unity destroyed the scriptableobjects and created missing references had nothing to do with serialisation, nor the way the assets where created.
The problem was : "A class must have the same name as its physical file on disk" A problem that neither c# nor unity complains about, and happily allows you to store more than one class in a file.
solution: Placing each script in a seperate file, fixed the problem.
That's strange, actually. Unity usually complains about that. Are you sure you don't get a warning / error inside the console?
From the engine's point of view there's no difference between a class derived from $$anonymous$$onoBehaviour or ScriptableObject. On the native side they use the same class for both so the same rules apply. Unfortunately the documentation doesn't mention that anywhere.
Apart from that it's in general recommended to only have a single class in a file and have the filename match the classname as it simplifies searching for a specific class and it also simplifies the management of classes / files inside the project. It's even recommended to place interfaces / enums definitions in a seperate file, though if an enum is tightly bound to a class it's fine inside the same file as the class.
Your answer
Follow this Question
Related Questions
An OS design issue: File types associated with their appropriate programs 1 Answer
How to access derived class members from base class type 1 Answer
C# serialization with polymorphism/inheritance. 1 Answer
Why is update calling both the base and overridden version of a method? 0 Answers
Skill system 0 Answers