Retrieve a derived class reference from a base class array

Hey everyone,

I have an array of my base class which is populated by derived classes.
The base and derived classes look like this:

public class BaseClass {

}

public class DerivedA : BaseClass {
     public someScriptableObject _data;
}

public class DerivedB: BaseClass {
      public someScriptableObject _data;
}

I then create multiple DerivedA(); and DerivedB(); and store them in a BaseClass[ ]. I’ve got a Fetch function that override the baseClass Fetch() in order to assign correctly my scriptable objects refs.

But when I try to access my _data var using:

BaseClass b = someBaseClassArray[0];
int someInt = (b as DerivedA)._data.someInt;

I got a null ref. Is it considered as object slicing ?
I found this question, which seemed to be answered using the same method that I’m using so I’m a bit confused. C# Accessing values of a derived class in an array of the base class - Stack Overflow

I know that I could put all my var inside BaseClass but I’d prefer If I could be able to contain everything in their proper class type and I need to keep all of this classes in the same array.
Is it something doable or a good practice at all ?

Thanks !

EDIT: Apparently, making BaseClass an abstract class could avoid slicing. However, I’m using a scriptable object to save/store my mapData and thus cannot use an abstract class as they cannot be serialized.

Update: Apparently, my scriptableObject MapData just forget what kind of classes where in the baseClass[ ]. I am not able to access anything related to my derived class when they have been stored and saved in the baseClass[ ] of a ScriptableObject.
Which I guess kind of change my question. How can I save a base class array of derived classes inside a scriptable object ?

No support for polymorphism (for non MonoBehaviour/ ScriptableObject objects). Unity - Manual: Script serialization

This might help, haven’t used it though Unity - Scripting API: SerializeReference

Thanks, so I need to write my own serializer ? Is it something complicated to do ?

Hey, Thanks for your answer. I spent at least 2 hours trying every possible combinations and cast to make sure that I didn’t do any mistakes. Even changed my BaseClass so that it inherited scriptable objects. Finally, the solution was to use [Serialize] header for my BaseClass which allowed me:

  • To make it abstract
  • To be able to cast DerivedClass stored in a List

Maybe I did a mistake earlier, but I did try everything and every possible combination and nothing worked. Meanwhile, the serialize header worked like a charm the first time.
Thanks :smile:

Usually casting to a derived type is a sign of poor design. What are you trying to do exactly? Is there a reason you can’t do something like this:

  public class BaseClass {
     public abstract int SomeValue { get ; }    
   }
    
   public class DerivedA : BaseClass {
       public ScriptableObject_TypeOne _data;

       public override int SomeValue { get { return _data.value; } }
   }
    
   public class DerivedB: BaseClass {
       public ScriptableObject_TypeTwo _data;

       public override int SomeValue { get { return _data.value; } }
   }

… to ensure a common interface for all objects consuming BaseClass?

Actually yes, I just didn’t thought about it !
Out of curiosity, why is casting a derived type is considered poor design ?

Type casting violates some common object-oriented principles.

If you are using inheritances, derived classes are supposed to act like base class, it you have object that rely on abstract class Fruit, it should work perfecly fine with Apple and Banana.

You should simply call “fruit.Eat()” without knowing fruit true type, that’s the whole reason of interfaces and abstract classes.

Otherwise you should always remember to go into all places when you work with Fruit and add another implementation for each new type.

If you are doing “If fruit is Apple then take data from Apple and do something with that data”, then you aren’t treating objects like objects, you are treating them like data structures, and it’s not object-oriented programming anymore.

1 Like

Thanks for the explanation.
You are right, I’m not tending toward an objected-oriented paradigm.
Basically, I’m working on a tactical game, and I’ve figured that I would make more sense to manage everything with data and managers rather than relying on scripts and entities. My tiles, collectibles and pawns are dummies: the gameobjects exists for the sole purpose of displaying a mesh or a sprite, the rest is done by data manipulation.
But now I’m wondering if that was a good idea.
My question was about my WorldObject class, from which are derived pawns, tiles and collectibles. I’m flipping through all of theses to find my pawns, tiles and other things I need to interact with during gameplay.

I doubt that such custom approaches will lead to maintainable code. Especially combining WorldObject (inheritance) with data approach, looks kinda weird.

If you aren’t willing to use OOP, which is perfectly fine, especially for games where OOP may be not the greatest choice, you can learn and read about ECS and check this library https://github.com/Leopotam/ecs.
ECS is paradigm based on data transformations and made specifically for game development. Maybe it’s something you want.