Best way to calculate damage of explosions
I've been wondering which way is the best to accurately calculate the damage an explosion supposed to deal while still being manageable to handle for a multiplayer game. By "accurately" I mean Line of Sight check as well as damage based on how much area of the player's colliders is exposed to the explosion. I've tried the following things so far:
Overlapsphere dealing damage to every "Player" component on a collider inside the radius. This was just a simple test to get to grips with the problem, as it obviously doesn't fulfill my criteria of being "accurate"
Find all colliders within Overlapshpere, shoot a raycast to each collider to check line of sight. As my player model is fairly complex (a human consisting of ~20 colliders) some colliders are hidden by others, meaning raycasts may hit the same collider twice. I simply changed it so that if a hit collider has the same root transform as the actual target collider (i.e. the same player) it still counts as a hit. The main problem however is that especially for larger colliders, a single raycast to the collider's gameobject's position is very accurate. For example, the chest is a single box collider, if the players chest is hidden by more than 50%, so the center of the collider is hidden, the raycast won't hit, despite a decent amount of the chest's area being exposed to the explosion.
Basically, a lot of raycasts. At first, all possibly hit players are stored in a dictionary by checking for colliders with a overlapshere and adding the Player ID (the name of the player gameobject which is individual) string as label to said dictionary, with a float as value (default 0). I have settled on 200 raycasts being drawn spherically using a for-loop with vectors from a pre-calculated vector array. Similar to the shrapnel of an actual explosion. For each raycast hit, the corresponding collider's root transform's name is being compared to the dictionary and then the float value is being increased by the damage of a single hit, let's say +5. If the explosion is going off in front of a player, a lot of raycasts will hit the player's colliders and the value in the dictionary will rise. After the for-loop I deal the corresponding damage to each player in the dictionary. If a player was further away or partially in cover relative to the explosion, he will have been hit by fewer raycasts and therefore less damage will be dealt.
System 3 works as far as I can tell the way I want it to, however I feel like it might by quite resource demanding to draw this many raycasts and I wonder if there may be a more elegant system to achieve my desired goals.
Thanks for reading and any help appreciated.
Answer by Jadlar · Aug 03, 2019 at 07:40 PM
Hi, i'm not sure what kind of game you are making at the moment but I have something similar with some tweaks. I'm making a 3D FPS at the moment and I use both raycast and overlap-sphere.
For mine instead of using 200 raycast i use about 10. First I use the overlap sphere to determine if the collider of an object is within the damage zone. Then, if an object is within an explosion radius then i draw 10 raycast: 1 on the head, 1 on the ground near feet, 4 in a even shape around the shoulders, and 4 near the knees in an even shape. Doing it like this allows you to check if the player is behind walls as well. If a point is hit then I calculate damage by (amount of points hit x base damage x distance from the center of collision). Use raycast hit.distance to find the distance from the hit point to the center of the explosion. Using this calculation works well for me. through play testing I set different distance variables to correspond with a damage multiplayer. For example in a 10 radius bomb if the a point of the player is hit within a 2.5 radius zone from the center I multiply ( one point hit x 0.20 x distance-check) distance-check in my case determines that the variable equals 1000 if a point is within a 2.5 radius space. Thus the damage taken is 200 guaranteeing me a instant kill (100 points of health 100 points of armor) from a grenade or rocket. Or if a single point is hit at radius 9 the variable = 90 (1 x 0.20 x 90) dealing 18 points of damage. Variables can be tweaked as needed.
The points to check for can also be attached to the skeleton of a model if that is something you are using. Hope this helps!
Your answer
Follow this Question
Related Questions
Raycast shooting impact effect position problem 1 Answer
AddExplosionForce not affecting every rigidbody 1 Answer
Spawning objects uNet Client and Local 0 Answers
Raycast over Photon 0 Answers