Search Unity

To send message or not.

Discussion in 'Scripting' started by bumble864, May 30, 2011.

  1. bumble864

    bumble864

    Joined:
    Jan 27, 2011
    Posts:
    128
    I was running on the treadmill today and as usual I was trying to figure things out for my game while running. and I came to this idea and I just wanted to run it by the community to see if this is a good idea and better than sending messages. I am a mostly novice scripter so bear with me please. Like most games I have the avatar, weapon projectiles, and enemies.

    Current design
    Player shoots the projectile
    Projectile hits the enemy
    Projectile sends message to enemy (damage, float) where float is the amount of damage the enemy takes
    Enemy reads message
    runs co-routine damage to apply damage to health.

    I keep reading that sending messages is slow and I would rather have something faster and that would send less messages for less traffic going on.
    New thought
    Player shoots the projectile
    Projectile hits the enemy
    On collision enemy health script reads projectile tag and applies X damage based on tag.

    In my head this sounds like a streamlined way of applying damage to the target without the use of sending messages. If I make one generic health script I can apply it to every enemy prefab I can have every enemy take the same amount of damage while being able to change their individual hit points. I can also just add other tags to the OnTriggerEnter for other weapons and they will be applied to every enemy automatically.

    Am I crazy? Does this sound like the right approach? Is there a better idea that I haven´t found yet?

    Thanks a bunch.
     
  2. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Good idea. (I can't handle a treadmill, but if it works for you, that's better than having to wait for good weather!)

    Your second approach sounds much better. The code is more decoupled. In the first scenario, there was no way to alter what damage the enemies were taking, for example. In general, when you can send events, and listen for them, you're going to be able to code in a less spiderwebbily entangled way.

    You may want to consider combining your own events with the ones that are built into PhysX. For example, if you have walls, and the projectile explodes on the wall, with your approaches, the enemy ships won't take any damage, even if they are right next to the explosion. I might still check to see if an enemy ship's collider was hit, and apply the most damage in that situation. But I might also check to see if any other ships were close enough to that explosion to be damaged. The way I would probably handle this, is to have a script on every enemy that listens for an explosion event, and applies damage if it happened close enough. Here is probably the fastest way to do it, which involves no control of the damage falloff curve, but could be easily altered to do that.

    Code (csharp):
    1. [SerializeField] float fullExplosionDamage; // set in Inspector
    2. [HideInInspector][SerializeField] float fullExplosionDamageOverSquareExplosionDamageThreshold;
    3.  
    4. // Calculate in a Reset function or something
    5. fullExplosionDamageOverSquareExplosionDamageThreshold =
    6.     fullExplosionDamage / (explosionDamageThreshold * explosionDamageThreshold);
    7.  
    8. // Do this every time there is a projectile,
    9. // or figure out how to do it more statically and then tell me about it.  ;-)
    10. projectile.OnExplosion += explosionPosition => {
    11.     float squareMagnitude = (transform.position - explosionPosition).sqrMagnitude;
    12.     if (squareMagnitude < explosionDamageThreshold)
    13.         health -= fullExplosionDamage - squareMagnitude * fullExplosionDamageOverSquareExplosionDamageThreshold;
    14. };
     
    Last edited: May 30, 2011
  3. hallamasch

    hallamasch

    Joined:
    Nov 29, 2010
    Posts:
    153
    I would probally let the projectile handle the damage.

    Pseudo Code:
    Code (csharp):
    1.  
    2. Class Enemy
    3. {
    4. int hitpoints = 100;
    5. int armo = 100;
    6.  
    7. void onDamage(int damage)
    8. {
    9.  
    10. // this way you can also do immunitys against lasers/photons/rockets
    11. hitpoints -= armor / damage <-- example, put something meaningfull here.
    12.  
    13. }
    14. }
    15.  
    16.  
    17. Class Projectile
    18. {
    19. int damage = 20;
    20.  
    21. virtual onCollisionEnter
    22. {
    23. Figure out what we hit, if it's of class type enemy --> call it's onDamage Method and pass our Damage Value
    24. Otherwise print a Decal on the Wall
    25. }
    26. }
    27.  
    28.  
    29. Class Bomb extends Projectile
    30. {
    31.  
    32. int radius = 5;
    33.  
    34. override void onCollisionEnter
    35. {
    36. For the bomb we want to cast an overlap sphere
    37. list of colliders = Physics.overlapSphere(radius)
    38.  
    39. foreach enemy in list of colliders
    40. {
    41. damageToApply = Calculate Fallof (enemy);
    42. enemy.onDamage(damageToApply);
    43. }
    44.  
    45.  
    46. }
    47.  
    48. void CalculateDamageFallof()
    49. {
    50. // Do something meaning full here.
    51. }
    52. }
    53.  
    54.  
     
  4. bumble864

    bumble864

    Joined:
    Jan 27, 2011
    Posts:
    128
    Guys,
    Thanks, for the advice.I'm gonna look into both tonight. So far I have Jessy's idea working and it's pretty nice so far. I can put the same script on everything, identify the health of the ship and everything else just goes into place.hallamasch, I will try your idea out next and see which works better. They probably both work just the same.
    I'm making a basic top down shooter with some friends just to get us out of the grind of our day jobs.

    I do have one other question though, Does a raycast have a tag?
    I have a "laser" type weapon and when it collides with a target the target needs to read it's being hit by a raycast. but I can't figure out the tag for raycast.
     
  5. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    The way you're trying to think about this doesn't seem like anything that I've encountered in Unity. You should be able to come up with a focused event system if you use the layerMask parameter of the Raycast function, though.