Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Ideal way to setup scripts for enemies w/ limbs for FPS?

Discussion in 'Scripting' started by billygamesinc, Feb 16, 2021.

  1. billygamesinc

    billygamesinc

    Joined:
    Dec 5, 2020
    Posts:
    246
    If I were to make enemies with different interactions based on which collider is hit. I'm actually not even using OnCollisionEnter at the moment but using raycast to detect the object and using the SendMessage command to activate the interaction (-1 HP, etc). However, I found out that SendMessage is not optimal and am looking for alternatives.

    1.Would attaching a script to every enemy limb cause performance issues even if they don't have Update() methods attached to them?

    2.The instantiated bullet is what will initiate the interaction, meaning I would have to attach each script to the prefab (public arm_script,public leg_script). This doesn't seem like a good way to do it either..

    How the interaction will play out in game:
    1.Zombie has 10 HP.
    2.The bullet's ray cast will hit the zombies arm.
    3.BOTH the zombie and it's arm will take damage.
    4.The arm will get destroyed at a certain threshold ( 4HP) while the zombie transform will die after 10HP is taken away.

    A simplified form of this would be something like a bullseye.



    If anyone knows what I should look into to optimize this interaction for multiple enemies it would be much appreciated.
     
  2. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    This sounds like a job for Interfaces!

    Basically, and interface class outlines what functions the inherited class must define. You can reference the inherited classes, all under the name of the interface class.

    This is a full example of how you would set this up in a unity environment. Unfortunately you cannot serialize an Interface class, so something like an Enum selector as a simple solution.

    *edited to make class names more readable...

    Code (CSharp):
    1. interface IEnemyController
    2. {
    3.     public void TakeDamage(int health, params string[] etc);  
    4. }
    5.  
    6. public class ZombieEnemyController : IEnemyController
    7. {
    8.     public void TakeDamage(int health, params string[] etc)
    9.     {
    10.         //Do Stuff...  
    11.     }
    12. }
    13.  
    14. public class TrollEnemyController : IEnemyController
    15. {
    16.     public void TakeDamage(int health, params string[] etc)
    17.     {
    18.         //Do Stuff...  
    19.     }
    20. }
    21.  
    22. /********************************************************************/
    23.  
    24. public class Enemy : MonoBehaviour
    25. {
    26.     [SerializedFrield]
    27.     private EnemyTypes enemyType;
    28.  
    29.     public IEnemyController EnemyController { get; set; }
    30.    
    31.     public enum EnemyTypes { Zombie, Troll }
    32.    
    33.     void start()
    34.     {
    35.         //define logic to decide on what you want. for example
    36.         switch(enemyType)
    37.         {
    38.             case EnemyTypes.Zombie:
    39.                 EnemyController = new ZombieEnemyController();
    40.             break;
    41.             case EnemyTypes.Troll:
    42.                 EnemyController = new TrollEnemyController();
    43.             break;
    44.         }
    45.     }
    46. }
    47.  
    48. /********************************************************************/
    49.  
    50. public class Player : MonoBehaviour
    51. {
    52.     void OnSomething()
    53.     {
    54.         //Get a reference
    55.         enemy.EnemyController.TakeDamage(...);      
    56.     }
    57. }
     
  3. billygamesinc

    billygamesinc

    Joined:
    Dec 5, 2020
    Posts:
    246
    Thanks! I'll look into it.
     
  4. billygamesinc

    billygamesinc

    Joined:
    Dec 5, 2020
    Posts:
    246

    I have a few questions about using interfaces.

    1.How would the interface know which enemy to send the function to? Ie Zombie1,Zombie2,Zombie3 all being the same type of enemy.
    2.How would each zombie subscribe to the interface? Would this be done manually with get component?
     
  5. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    So whatever object was calling the send message in your original method. That method would have a reference to the interface, and instead call the interface method. The object associated with said collision, would have the the class that inherits from the interface.

    Below is just one way you could do it. Its better to learn how to use it, then determine the best approach for your needs.
    Fore example:

    Code (CSharp):
    1. class Player : MonoBehaviour
    2. {
    3.     OnColiisionEnter(col)
    4.     {
    5.         Enemy = col.GetComponent<Enemy>();
    6.         if (enemy)
    7.         {
    8.             enemy.enemyInterface.XXXXXXXXXX();  
    9.         }
    10.         else
    11.         {
    12.             //Not an enemy object
    13.         }
    14.     }  
    15. }
    16.  
    17. public class Enemy : MonoBehaviour
    18. {
    19.     public IEnemyInterface= enemyInterface;  
    20. }
     
  6. billygamesinc

    billygamesinc

    Joined:
    Dec 5, 2020
    Posts:
    246
    I managed to get it working somewhat, instead of using oncollision enter I just use the raycast to get component. Thank you!