Search Unity

how would you guys handle enemies knowing about player.

Discussion in 'Game Design' started by simonlvschal, Nov 12, 2018.

  1. simonlvschal

    simonlvschal

    Joined:
    Nov 17, 2015
    Posts:
    266
    so the question might be abit vague. and might not be anything to do with game design in general. but i couldnt exaclty find the spot on the forum as to where this should be asked in.

    so my problem is not really coding wise but its more of a choice of having to give the enemies full knowledge of a player. aka health,abilites, etc or should i approach is differently? the main reason for this is obviously because it might be a security problem if i have a open hole in the code.

    so my question is how do you guys handle Reducing health on enemies/players. without doing heavy Calls like GetComponent and note this component call would be every single time u get the health of a player..

    also this is intended for mobile games
     
    Last edited: Nov 12, 2018
  2. Steve_Stevens

    Steve_Stevens

    Joined:
    May 3, 2016
    Posts:
    35
    anything that bleeds has a Damage or Health class that is a BASE class. You can then create a class that inherits the base class and adjusts methods inside that class. So basically, when your weapon/bullet/whatever hits something, you check if it has the Damage class as a component. Inside that damage class is something that takes hit points away from whatever it is that got hit. Player, NPC, Enemy, Wall, Building, Animal, etc.. The BASE class does the heavy lifting as far as taking away the hit points, and your Objects class can add anything extra. PLUS you keep all your variables private because your base class has all the methods to hand out damage and trigger events.
     
  3. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    GetComponent is actually not that heavy, it's more on par with the .transform call. It's still interop though. Unless you're doing 10k+ per frame you won't notice the hitchup.

    GetComponentInChildren is heavier, since it requires to check current gameObject attached components, and then recursively each gameObjects' component table of the children components.

    GetComponentInParent even heavier, for the same recursive reasons.

    Usually what I do is use .GetComponent<Entity>() to find a specific entity by something like physics query. Then, perform each required action on it directly. This also means it has internal functionality for each action required. Usually this is enforced by using interfaces.

    If you need a specific action set, you could do GetComponent<ISomething>() instead. This will fetch exactly what you need without even knowing base class type. Inheritance is a bad thing, because of virtual calls + design spahetti of the overrides.

    Using interface is most of the times are plenty, and highly advised. Plus, you can slap a lot of them, where as multiple inheritance in C# is not allowed.

    Also, you can even create a reference component, and fetch it via GetComponent<T> to point to a specific object. It is faster than using GetComponentInParent<T> or GetComponentInChildren<T>.
    That way you'd always have a reference to the main class of the hit entity if you have complex hierarchy of colliders.

    TL;DR:
    GetComponent<T> is not that heavy.
    Use interfaces instead of spahetti-designed base classes.
    Use composition instead of inheritance.

    If in doubt about performance - use ECS + burst. OOP sucks anyway nowadays.
     
    Last edited: Nov 12, 2018
  4. simonlvschal

    simonlvschal

    Joined:
    Nov 17, 2015
    Posts:
    266
    the thing is GetComponent is heavy. and its even worse for mobile. hence why i am trying to find a solution that goes around it
     
  5. Magician_Arcana

    Magician_Arcana

    Joined:
    Aug 23, 2015
    Posts:
    47
    What I do if I need to call getComponent is I try to keep those calls in the start function if possible. If it needs to be called in the update function, naturally I'd use a conditional to make sure it's only called when absolutely necessary.

    So for example, if your enemy class needs a reference to the player, have a variable that's like "playerClass targetPlayer" in that class, and in the start function set that reference like "targetPlayer = .findWithTag("Player").getComponent<playerClass>()"
     
  6. simonlvschal

    simonlvschal

    Joined:
    Nov 17, 2015
    Posts:
    266
    ye i know that. i am just saying i am trying to avoid get component calls where i know i need to do it more then once.

    which i managed to avoid quite well so far
     
  7. LMan

    LMan

    Joined:
    Jun 1, 2013
    Posts:
    493
    The usual solution for when something you need often is expensive to get is to cache it in memory so that it is always available. A common approach is to have a singleton manager object that makes these references available.

    The solution for security concerns is access control- instead of marking variables public, make read-only properties. This is why all c# variables are private by default.
     
  8. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I'm not saying that you're wrong, but you are.
    If in doubt - use profiler and make some tests. But not in the editor, as it produces overhead and security checks.
    There's plenty of cases where single .GetComponent<T> per frame / action is much more efficient. As a mobile dev, I can freely tell you that.

    Alternatively, if you're so obsessed with .GetComponent<T> being called at all - make a lookup on your own.
    Dictionary <Transform, YourComponent> for example. It might be faster, but that will cost you time to sustain it, plus, memory.

    Note that even in this case you'll be accessing extern transform. Plus, adding / removing entities constantly from / to it. Thats op lost already.

    Here's some old related topics:
    https://snowhydra.wordpress.com/2015/06/01/unity-performance-testing-getcomponent-fields-tags/
    https://gamedev.stackexchange.com/q...ternative-to-a-getcomponent-from-a-raycasthit
    http://chaoscultgames.com/2014/03/unity3d-mythbusting-performance/

    I'd say, you're optimizing the wrong thing here. Make sure it is the culprit.
    Also, I'd say you're using it wrong, if you need to optimize it.
    Post your code snippet, maybe it will be easier for us to understand where the actual problem lies.
     
    Last edited: Nov 12, 2018
  9. simonlvschal

    simonlvschal

    Joined:
    Nov 17, 2015
    Posts:
    266
    so this is some of the ways i am approaching my design atm

     
  10. newjerseyrunner

    newjerseyrunner

    Joined:
    Jul 20, 2017
    Posts:
    966
    I have a HealthManager class which handles the health for any destructible entity in my game. This includes the player, all of the enemies, the vehicles, barrels, even destructible walls. Every type of entity that uses it has a public HealthManager m_health component, which is a reference to the component.
     
    Murgilod likes this.