Collisions, tags, and enemy types

Hi there - I’m new to object-oriented thinking and have what may be kind of a philosophical question about it. Would love any help anyone can provide.

So, I’ve got my little space shooter game, and I’ve got my script on a “player shot” prefab, controlling how player projectiles work. To make them affect enemies, I call OnCollisionEnter, and then I check the enemy’s tag. What that means in practice is I have what feels like redundant code for each enemy type, and it feels a little clunky:

if (hitInfo.gameObject.tag == "Greeble") 
{
var greeble : Greeble;
greeble = hitInfo.gameObject.GetComponent("Greeble");
greeble.IsHit(damage);
Destroy(gameObject);
}

if (hitInfo.gameObject.tag == "Jubbler") 
{
var jubbler : Jubbler;
jubbler = hitInfo.gameObject.GetComponent("Jubbler");
jubbler.IsHit(damage);
Destroy(gameObject);
}

[etc, etc]

On the other side of things, each enemy has a script which includes a function (IsHit) telling it what to do. Now, I could write an IsHit script by itself, that I could then attach separately to each enemy, and I get the sense that’s “the right thing” as far as OOP theory goes, and might make this section cleaner. But that seems a little clunky too, especially since, 1, it feels awkward to have a whole script for a function that pretty much just decrements a variable; and 2, if I want to have certain enemies react differently to getting hit, they couldn’t use generalized IsHit code anyway.

Is there a really simple and obvious way to do this? (Am I being a total greeble?) Right now it does work, and it’s not even that much trouble to just duplicate the code in the player shot script for each new enemy type. It’s more just a question of whether I could be doing the whole thing more efficiently.

Any advice would be hugely appreciated–thanks!

Couple of things…

  1. I’d use a trigger instead of a collider for your projectile, since you’re using it as a trigger anyways.
  2. I’d depend less on tags and more on OO classes. Tags are very short-sighted and one-dimensional. You’re seeing the effect of that here.
  3. I’d change the method name “IsHit” to something else. It sounds more like a method you would use to check if it was hit, rather than perform a Hit on it. Rule of thumb for me, use Verbs for things that perform an action, and use Get or Is for queries.

So here’s a possible setup of classes that use inheritance:

GameObject
|-Unit
  |-Enemy
    |-Greeble
    |-Jubbler

In this case, Unit class would have the IsHit method, as any unit can be hit. Then since Greeble and Jubbler extend Unit, they have the method too. Then the following code is usable:

//Get the base-class Unit from the hit gameobject
Unit hitUnit = hitInfo.gameObject.GetComponent<Unit>();
hitUnit.IsHit( damage );

You can get much more complex and abstracted with your design, like having a Damageable interface that Unit implements, but this works for now and is a good use of Inheritance.

I highly recommend you do some learning on Inheritance as it is the most beneficial programming technique I know of. You’ll see yourself using it everywhere and wonder what you did without it :slight_smile:

Hope this helped!