Inheritance & Polymorphism

I’m about to start developing my first serious game, and I want to practice good OOP and OOD along the way. Specifically, I want to take advantage of inheritance and polymorphism using super classes and derived classes.

I’m confused about how to do this in Unity because of it’s component based system. Is this possible? If so, how can it be done?

P.S. Coding in C#

Okay, so this should probably be on the forums, as it’s kinda open ended and not really a question, but since it’s interesting and important, I’ll let it through and give my thoughts.

So, you are correct in that Unity uses components, but that does not mean that you’re out of luck with polymorphism. In fact, you are always using it when you’re scripting in Unity, though in a bit of a roundabout way, as you’re inheriting from the superclass Monobehaviour, and overriding* it’s defined Awake, Start, Update and so on methods.

So, a very common example of how you’d use a type hireachy would be for different “living” entities in your game. Say you’re making any kind of game where there’s both players and opponents, and both of those have stuff in common, like health, and moving about and taking damage. In that case, you’d have some kind of (probably abstract) superclass of these:

public abstract class Entity : MonoBehaviour {

    int health;

    public virtual void Damage(int damage)
    {
        health = Mathf.Max(0, health - damage);
        if (health == 0)
            Die();
    }

    public virtual void Move(Vector3 direction)
    {
        //Movement code!
    }

    public abstract void Die();
}

You’ll end up with something a lot bigger, but this is the gist of it. Note that while every creature can die, the Die method probably needs to be abstract, as what happens when NPCs and PCs die are very different. This script could also be used for stuff like obstructions that you can damage and destroy - think bushes in Zelda - in which case you’d have Move in a more specific (still abstract) “Moving Entity” subclass, and not here.

Now, you’d implement both Player and Enemy classes, both inheriting from Entity (again rudimentary examples):

public class Player : Entity {

    void Update()
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");
        Move(new Vector3(x, 0, z));
    }

    public override void Die()
    {
        //Respawn or something
    }
}

public class Enemy : Entity {

    Player player;
    void Start()
    {
        player = FindObjectOfType<Player>();
    }

    void Update()
    {
        Vector3 direction = player.transform.position - transform.position;
        Move(direction);
        //Attack if close enough or something like that
    }

    public override void Die()
    {
        //Play an animation or instantiate an death-effect or whatever
        Destroy(gameObject);
    }
	
}

This kind of stuff enables you to do all of the good things you usually can do with polymorphism - specifically making more general algorithms, and avoiding code replication. For instance - if you want to have an explosion that damages both enemies and players, you could find all objects within range that’s of the type Entity, and call the damage method on them, instead of having to handle players and enemies. If you had some kind of grenade, you could implement it like this:

void Explode()
{
    Collider[] allHit = Physics.OverlapSphere(transform.position, 5f);

    foreach (Collider c in allHit)
    {
        //This will find both players and enemies hit by the overlapsphere.
        Entity hitEntity = c.GetComponent<Entity>(); 
        if (hitEntity != null)
            hitEntity.Damage(2);
    }
}

I use these kinds of techniques a ton. Everything that moves about in my games moves with the same method at the base, and the same goes for health and stamina and other common things (if applicable)

You can also use interfaces for a lot of this stuff - whenever there’s different things that takes input, but does vastly different things when given that input (say something like Half Life 2, where you occasionally drive a vehicle around), I’d use something like an InputReceiver interface that defines methods for handling the different inputs. Then you can have an InputController class that handles reading player input, and sends that input to the currently registered InputReceiver, not caring whether that receiver is the character, a vehicle, a menu or something else.

In general, whenever you’re implementing something, stop and ask yourself:

  • Is this similar in nature to something I’ve already implemented?
  • If yes: does it make sense to take the old implementation and turn it into a generalized algorithm?

If you want a longer discussion, I’d suggest opening a post on the forums. I’d happily answer more detailed questions and come with more examples.

*Okay, you’re not really overriding them. What’s actually happening is that reflection is used to call the methods with specific names if they exist. There’s probably a good reason to do this, but I don’t know exactly why.

It’s possible but not entirely necessary or useful for a “serious” game. I recently started using it in my project and found that I really don’t know C# as well as I thought and wasted a lot of time trying to figure out how to override & call the base of the standard MonoBehaviour callbacks like Start and Awake. I’m going to avoid it in the future because it’s just so much easier to create a script for each instance where polymorphism would be useful.

(i.e. instead of having Truck and Car inherit Vehicle it’s easier to have a gameobject with truck script + vehicle script, or car script + vehicle script)