Search Unity

Realistic-Accurate grenade

Discussion in 'Scripting' started by zahovic3162, Jun 18, 2018.

  1. zahovic3162

    zahovic3162

    Joined:
    Jan 3, 2016
    Posts:
    41
    I want to make realistic greande simular to real life. It mustn't throw people around it will just hurt, kill or won't do anything to people in 20 meter range. I have no idea about this topic how should I do it? My game is arma 3 + insurgency kinda game and it is multiplayer.
     
  2. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Do a Physics.OverlapSphere and check wich players are inside range. Then do a raycast to each transform holding a hit box. Its not perfect but pretty good
     
    zahovic3162 likes this.
  3. zahovic3162

    zahovic3162

    Joined:
    Jan 3, 2016
    Posts:
    41
    thank you
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    An easier route could be that you have a SphereCollider flagged as Trigger attached to your grenade (as a child). Then when you throw it and it time passes you enable that collider's gameobject, and any thing it overlaps gets damaged (using the OnTriggerEnter message/event).
     
  5. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    That will not take into account people behind cover
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    And follow with the raycast.

    Note I call this easier from a design perspective. It allows you to have a visualization of the grenade hit area, and allows you to write a reusable 'overlap weapon' for AOE's of any shape by replacing the collider.
     
  7. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    In this case its just a radius, but you could make a custom gizmo if you have many explosives to configure.

    Talking about explosives, @BarbarZahoCan, I would use composition over inheritance here. If you have a base grenade class with explosive behaviour, you cant re use it for a bomb or c4. So create a component that takes care of the explosive parts of the grenade
     
    zahovic3162 likes this.
  8. zahovic3162

    zahovic3162

    Joined:
    Jan 3, 2016
    Posts:
    41
    I make really few weapons but I try to make them perfect instead of filling the game with clunky guns and equipments
     
  9. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    How did it went? Here is our code if it can help

    Code (CSharp):
    1. namespace Weapons.Explosives
    2. {
    3.     public  class Explosive : MonoBehaviour
    4.     {
    5.         public Transform ExplosionCenter;
    6.         public GameObject ExplosionPrefab;
    7.  
    8.         private float ExplosionRadius = 15f;
    9.         private float InjuryRadius = 13f;
    10.         private float FatalRadius = 6.5f;
    11.  
    12.         private NetworkTrackedObject network;
    13.      
    14.         protected void Awake()
    15.         {
    16.             if(ExplosionCenter == null)
    17.                 ExplosionCenter = transform;
    18.  
    19.             network = GetComponent<NetworkTrackedObject>();
    20.             network.RegisterRpc(this);
    21.         }
    22.        
    23.         public void RequestPerformExplosion()
    24.         {
    25.             var hits = GetHits();
    26.             var avatarIds = hits.Select(x => x.Player.NetworkedId).ToArray();
    27.             var damage = hits.Select(x => x.Damage).ToArray();
    28.             var diedStatus = hits.Select(x => x.Died).ToArray();
    29.  
    30.             //Order here is important, first send to client then call local, becasue some listeners of ExplodedEvent performs delete (handgrenade) and that will make the networkcode ignore RPC because of deleted local gameobject (maybe candidate for refactor?)
    31.             network.RPC("PerformExplosion", NetworkReceivers.Others, ExplosionCenter.position, avatarIds, damage, diedStatus);
    32.             PerformExplosion(ExplosionCenter.position, avatarIds, damage, diedStatus);
    33.         }
    34.  
    35.         [BRPC]
    36.         public void PerformExplosion(Vector3 explosionCenter, ulong[] avatarIds, float[] damage, bool[] diedStatus)
    37.         {
    38.             var avatars = avatarIds
    39.                 .Select(id => AvatarBase.AvatarBases[id])
    40.                 .ToList();
    41.  
    42.             var grenadeHits = new List<GrenadeHit>();
    43.  
    44.             for(int i = 0; i < avatars.Count; i++)
    45.             {
    46.                 grenadeHits.Add(new GrenadeHit(avatars[i], damage[i], diedStatus[i]));
    47.             }
    48.  
    49.             PerformLocalExplosion(explosionCenter, grenadeHits);
    50.             network.interactable.Publish(new ExplodedEvent()); //TODO: We should fix so not only NVRInteractibles can fire scoped events
    51.         }
    52.  
    53.         private IEnumerable<GrenadeHit> GetHits()
    54.         {
    55.             var avatars = Physics.OverlapSphere(ExplosionCenter.position, ExplosionRadius, LayerMask.GetMask(Layers.Player))
    56.                 .Select(x => AvatarBase.GetHitZone(x.transform).Avatar)
    57.                 .Distinct()
    58.                 .ToList();
    59.  
    60.             var validHits = RemoveOccludedHits(avatars).ToList();
    61.  
    62.             return validHits.Select(x => new GrenadeHit(x, GetDamage(x))).ToList();
    63.         }
    64.  
    65.         private IEnumerable<AvatarBase> RemoveOccludedHits(IEnumerable<AvatarBase> avatarsInRange)
    66.         {
    67.             foreach(var avatar in avatarsInRange)
    68.             {
    69.                 var mask = LayerMask.GetMask(Layers.Ground, Layers.Default, Layers.WorldItems);
    70.  
    71.                 foreach(var part in avatar.HitZones)
    72.                 {
    73.                     RaycastHit hitInfo;
    74.                     if(Physics.Raycast(new Ray(ExplosionCenter.position, part.transform.position - ExplosionCenter.position), out hitInfo, 30, mask))
    75.                     {
    76.                         if(Vector3.Distance(ExplosionCenter.position, hitInfo.point) >
    77.                             Vector3.Distance(ExplosionCenter.position, part.transform.position))
    78.                         {
    79.                             yield return avatar;
    80.                             break;
    81.                         }
    82.                     }
    83.                     else
    84.                     {
    85.                         yield return avatar;
    86.                         break;
    87.                     }
    88.                 }
    89.             }
    90.         }
    91.  
    92.         private float GetDamage(AvatarBase playerAvatar)
    93.         {
    94.             var distance = Vector3.Distance(playerAvatar.transform.position, ExplosionCenter.position);
    95.  
    96.             if(distance < FatalRadius)
    97.             {
    98.                 return 110;
    99.             }
    100.  
    101.             if(distance < InjuryRadius)
    102.             {
    103.                 var damage = (1 - (distance - FatalRadius) / (InjuryRadius - FatalRadius)) * 95;
    104.  
    105.                 return damage;
    106.             }
    107.  
    108.             return 0;
    109.         }
    110.  
    111.         private void PerformLocalExplosion(Vector3 explosionCenter, IEnumerable<GrenadeHit> hits)
    112.         {
    113.             var explosion = GameObject.Instantiate(ExplosionPrefab);
    114.  
    115.             explosion.transform.position = explosionCenter;
    116.  
    117.             foreach(var hit in hits)
    118.             {
    119.                 hit.Player.RegisterExplosionHit(network.OwnerId, 800, InjuryRadius, ExplosionCenter.position, hit.Damage, hit.Died);
    120.             }
    121.         }
    122.     }
     
  10. zahovic3162

    zahovic3162

    Joined:
    Jan 3, 2016
    Posts:
    41
    I am not on grenade right now but looks like it is easy. I am polishing the animations for now grenade is optional I have kind of a milestone after that I will add the grenade probably becouse it is a really important factor in real life firefights and I want my game to feel really hardcore and realistic. Thank you for all of your help
     
  11. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Btw I think you should have some force effect on the ragdolls, but don't over do it, here is how it looks in our game

     
    zahovic3162 and Mauri like this.
  12. zahovic3162

    zahovic3162

    Joined:
    Jan 3, 2016
    Posts:
    41
    lmao :D I will add some ragdoll effects but it will be so little that it will only be able to move limbs a little