Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Need some help for enemy class design

Discussion in 'Scripting' started by nicklowkc1, Aug 10, 2019.

  1. nicklowkc1

    nicklowkc1

    Joined:
    Feb 27, 2019
    Posts:
    28
    Hi all coders!
    I am currently creating a simple jrpg type game that has a tile map and battle system when encounter an enemy. I already got a very simple, nothing fancy battle system working. The current design for my enemy is by attaching a component to the game object, for example a EnemyGhost component and the component is inherited from monobehaviour. I estimate this kind of design will become extremely messy when I have more enemies, say like EnemyGoblin, EnemyOrc etc. And since every enemy has different skill and attack i am guessing using interface will solve the problem. For the enemy data, I created a scriptable object and assign the data to those enemies at inspector.
    The question I wanna ask is, am I designing/managing this correctly?

    Thank you
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    First of all, are you manually placing enemies and then attaching scripts to them? If that's not absolutely necessary, i'd go with a more script-based approach. First of all, you are right in that you should define an abstract class or interface called "Enemy". This then predefines necessary methods like "Attack(Other o)" or "GetCurrentHP()", .. and other things that every enemy type has to have.
    You can then specify enemy types like EnemyGhost that implement or inherit from Enemy, which requires EnemyGhost to implement its own version of "Attack(Other o)" and so on, enabling you to have a structure every enemy follows (ie, every enemy has an attack function), but allowing you to fully customize how each enemy handles attacking.

    Somewhere you have a "List<Enemy> allActiveEnemies" to keep track of all spawned enemies. This list is of type Enemy, so it can contain any subtype of Enemy, like EnemyGhost. This enables you to have all your enemies in one list and, for example in a turn based game, iterate through the list and call "Attack(Other o)" on all the enemies, so that they all attack.
    When spawning a new enemy you simply create the desired enemy type, like EnemyGhost e = new EnemyGhost(position, rotation, whateverElseYouNeed), and add it to the list of allActiveEnemies. The constructor of the EnemyGhost class would, on creation, handle the creation of the corresponding GameObject, including its model, textures, and so on.

    Hope this helps.
     
  3. nicklowkc1

    nicklowkc1

    Joined:
    Feb 27, 2019
    Posts:
    28
    Hi Yoreki,

    Thank you for your reply. In this case I need to let the Enemy base abstract class inherited from monobehaviour am I right? I am assuming that I have to create a Enemy Manager object that has List of enemy that can be instantiated on start. I was going to manually placing them on the scene but it seems like instantiating through code doesn't seem bad for me too.

    Thank you.
     
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    You will need some sort of central Manager class to keep track of enemies and what they do, yes. Depending on the size of your game you may want to make an EnemyManager, or simply a WorldManager (which manages Enemies, but also other stuff you are doing later) or something along those lines. That's a design decision you have to make.

    Also, i dont think you actually need your Enemy's to inherit from Monobehavior (but you could do that if you want).
    You dont need the Start() function as you can simply do whatever you would do in it in the class constructor. And in case you need an Update function, you could simply define that yourself in Enemy and fill in the specifics for each subtype like you would if it was a monobehavior. This could save you a lot of overhead, especially if you plan on having many enemies. The only difference would be that you had to call Enemy.Update() for each enemy manually. However, since your Manager class would inherit from Monobehavior, you could use its Monobehavior.Update() to loop over all enemies and call enemy.Update(), which would effectively be the same as having enemy.Update() be called by Unity each frame.
    So unless you specifically need something else from Monobehavior i would rather let the manager take control over updating your enemy list, but this again is up to you.

    Hope this explanation makes sense. If it's confusing i'll try again with some examples.
     
    nicklowkc1 likes this.
  5. nicklowkc1

    nicklowkc1

    Joined:
    Feb 27, 2019
    Posts:
    28
    Hi yoreki, thanks again for you reply.
    I will try the method you described tonight :)
    My previous class design kinda messed up lol.