- Home /
How to access derived class members from base class type
I'm having some trouble when it comes to using derived classes with scriptable objects. More specifically accessing derived class members from a base class type. The TL;DR is I've been attempting to store derived classes as base classes and then access members in the derived class. I understand that a cast is required in order to access the derived class members but I'm struggling to find a clean implementation.
public class A : ScriptableObject
{
[SerializeField]
float baseClassValue;
}
public class B : A
{
[SerializeField]
int derivedClassValue;
}
public class C : Monobehaviour
{
//Scriptable object to be assigned in inspector
public A a;
void Start()
{
B b = (B)a;
Debug.Log(b.derivedClassValue);
}
}
For a small number of derived classes this approach can work, but what if I end up with class D,E,F and so on all inheriting from A, all with members not contained in the base class. Either I have to create a variable of type B,D,E... and assign the scriptable object of the same type there in the inspector, or I end up with a horrible chain of if statements to determine what type to cast to.
if(a is b)
{
B b = (B)a;
}
else if(a is d)
{
D d = (D)a;
}
//....
While this can work I'm trying to make this easy to read and extend with more derived classes, does anyone know of a better way, or am I approaching the problem in completely the wrong way?
Thanks in advance for any answers.
Answer by Bunny83 · Jan 29, 2019 at 05:56 PM
One solution would be to avoid inheritance completely and use interfaces instead. However this of course only makes sense if the classes have something in common which you can actually treat in an abstract way. For example:
public interface IValue
{
float val {get;set;}
}
public class A : ScriptableObject, IValue
{
[SerializeField]
float someValue;
public float val
{
get { return someValue;}
set { someValue = value;}
}
}
Note that Unity can't directly serialize interface references. So to refer to a class which implements the "IValue" interface you would do
[SerializeField]
float UnityEngine.Object a;
IValue val = a as IValue;
if (val != null)
{
Debug.Log("Val: " + val.val);
}
Now you can assign any instance (ScriptableObject or MonoBehaviour derived class) to the variable "a" in the inspector. At runtime you would check if the class implements the IValue interface and you can read / write the corresponding variable of that instance. Though of course this only works if the variables you want to treat generically have the same type. If your classes have different variable types i really do not understand your abstract example usecase in your question.
What exactly do you want to do in the code fragment where you access your variable "a"? Do you have a more concrete example?
Thanks for the response, interfaces are something I've only used briefly and it's definitely an area I want to explore more. To add more detail to my original issue, I've created a 'stat' class which I've then used to derive stats such as hp/movespeed/damage etc. Along side this I have created an abstract enemy scriptable object that I've used to derive enemies such as goblin/skeleton.
When setting up the goblin prefab, I'm adding the goblin scriptable object to a setup component that then adds all the relevant stat components, this component will accept any scriptable object of type enemy.
Once a stat component has been added, it gets a reference to the setup component and sets it's base value based on the scriptable object. The problem arises when the stat component checks the setup component as it doesn't know if it's a goblin or a skeleton without explicitly checking for each one.
I'm thinking my approach to the problem is wrong here rather than the specific implementation, passing the base value onto the component when it's created might work out a better solution
Your answer
Follow this Question
Related Questions
An OS design issue: File types associated with their appropriate programs 1 Answer
Polymorphic Scriptable Object 2 Answers
unity doesn't recognize the derived class 3 Answers
ScriptableObject : Serialized Polymorphism Classes Can Not be Deserialize with Polymorphism 1 Answer
C# How to derives A from B, where B in different .cs file 1 Answer