Will my idea for organizing different enemies work and is it best practice?

Hello all!

I’m very new to coding so please bear with me. My game features a ton of different enemies. Upon colliding with the player, each enemy runs a different function, causing UI elements to change depending on what enemy was collided with.

I am brainstorming what would be the best way to allow my game to recognize which enemy collided with the player and run the corresponding behaviour for that specific enemy.

I guess the easiest way would be to just slam 30 different if statements searching for each enemy tag into a void update() but that’s obviously awful practice as I’d be running so many different checks every frame.

Then I perhaps thought I could just stick those 30 if statements into their own void enemies() function and only call the function when the player bumps into an enemy. This sounds better since it’s not every frame but at the end of the day, I’ll still be running up to 30 different if statements every time I bump into an enemy.

Then I figured, what if I set up a separate function for each enemy that is identical to its tag (i.e. enemy with tag “orc” would get a void orc() function in the Game Manager. Then, I set up my Game Manager to grab the tag of the collided enemy as a string whenever the player collides with an enemy and run void “string”(). This way, I wouldn’t even have to run through all the 30 if statements and I could just skip right to the appropriate function for each enemy.

Would this be possible? Or am I way off base here? Is there a better upgrade I could make to organizing a system for recognizing what enemy my player bumps into and running the appropriate behaviour for each unique enemy upon collision?

Thank you for your time!

Yeah, no matter where they go, a chain of if statements is always bad practice.

This could be done with Reflection, but it’s really bad practice. Reflection is slow, it may not work on all platforms, makes your program insecure (what if some player finds a way to set a tag to “DestroyEnemy”, and calls your DestroyEnemy() function?), and makes your program vulnerable to typographical errors (if you misspell something, you have to play through the entire game to find out there’s an error, instead of getting a compiler error the instant you mistype it). Reflection is a tool of last resort when absolutely nothing else works.

What you want is inheritance and polymorphism. Google around with those words for a tutorial you like, but essentially you will have a base “Enemy” class with a virtual function: (virtual here means, it can be overridden)

public class Enemy : MonoBehaviour {
   public virtual void Behave() {
      Debug.Log("Basic behavior code goes here.");
   }
}

And then each enemy will derive from that class (put “Enemy” after the : in the class definition) and overrides its behavior:

public class OrcEnemy : Enemy {
   public override void Behave() {
      Debug.Log("Be an orc");
   }
}

When you find the enemy on the collision, you can call GetComponent() and it will find not only Enemy, but also any class that derives from Enemy, including OrcEnemy. You can then call enemy.Behave(), and it will call the Behave() method of that object, even if you’ve overridden the base function.

var enemy = collision.other.GetComponent<Enemy>();
enemy.Behave(); // if we collided with an orc, it will print "Be an orc"

A tutorial will fill in more info about inheritance, but that’s more or less how you’d apply it to your situation.

1 Like

Thank you for such a detailed response! I previously used inheritance for some other super minor stuff but for whatever reason, I never thought to use it like that. Sounds robust and easily expandable which is exactly what I needed. Thank you for the help!

StarManta’s post is right on, and additionally you can do a lot with interfaces.

For instance in C# you can only inherit from one thing, eg, an Enemy.

Something might have other characteristics that are shared by many different objects and this is a great use for interfaces, which you can implement as many of them as you want.

Using Interfaces in Unity3D:

Check Youtube for other tutorials about interfaces and working in Unity3D. It’s a pretty powerful combination.

These other approaches are excellent, it’s a perfect case for inheritance.

One thing:
“I guess the easiest way would be to just slam 30 different if statements searching for each enemy tag into a void update() but that’s obviously awful practice as I’d be running so many different checks every frame.”

Understand that you don’t check this in Update(), it’s in OnCollisionEnter(). Unity handles the collision checking and only runs that when something collides.

You can use a switch statement or if/else in OnCollisionEnter and check for all tags. That’s the non-inheritance way to do it. I recommend using inheritance, but you can “brute-force” it. Checking 30 tags is a non-issue for the processor (even though it seems like a lot)…it’s a simple comparison.

1 Like