- Home /
How can I apply damage based on a grenade explosion, but test whether the objects are behind cover so they are not damaged even within the explosion radius?
I was wondering if it is possible to have a object shoot out rays in all directions. I want this for a grenade, as i want it so when the grenade blows up it shoots out rays in all directions, and if a ray hits something it will apply damage. I want to do it with ray casting because i want it so if the player is behind cover they will not get hurt, unlike if i spawned a trigger to check for collisions with player, as that would go threw walls. IF you got a better way of doing it please tell me otherwise help me the best you can. Also, can you have it set so it will calculate the length of the ray? U would like that as it would make it easier to apply damage, if the player is on top of the grenade it is instant death, within 1 meter is half health, and within 5 meters is 25% of the health. I would set the ray to be about 6 meters long if i could calculate the length of it.
@duck the script works well. the only problem is if a player is in front of another player. the player behind it would not take the damage.
how do i fix that?
also heres the code.
float power = 100;
int damage = 1;
float radius = 100f;
void Start()
{
}
void Update()
{
if (Input.GetButton("Fire1"))
{
Explode();
}
}
void Explode()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, radius);
Debug.Log("Count of colliders = " + colliders.Length);
foreach (Collider collider in colliders)
{
if (collider.tag == "brick" || collider.tag == "Player")
{
Debug.Log("Found brick or a player");
Debug.Log("collider is " + collider.name);
RaycastHit hit;
if (Physics.Linecast(transform.position, collider.transform.position, out hit, 5) ) // collider.tag != "Player" || collider.tag != "brick")
{
if (hit.collider == collider)
{
Debug.Log("No obstructions");
if (hit.rigidbody)
hit.rigidbody.AddExplosionForce(power, transform.position, radius, 50f);
}
}
}
}
}
Answer by duck · Apr 23, 2010 at 03:14 PM
I would do these calculations in the opposite order:
- find all damagable objects within the radius
- cast a ray from the grenade to each found object, to test whether they are shielded
For more information, see this answer which discusses how to apply damage which falls off within a certain blast radius, and just add the raycast test to it, to check for cover.
function AreaDamageEnemies(location : Vector3, radius : float , damage : float ) { var objectsInRange : Collider[] = Physics.OverlapSphere(location, radius); for (var col : Collider in objectsInRange) { var enemy : Enemy = col.GetComponent(Enemy); if (enemy != null) { // test if enemy is exposed to blast, or behind cover: var hit : RaycastHit; var exposed = false; if (Physics.Raycast (location, (enemy.transform.position-location), hit)) { exposed = (hit.collider = enemyCollider); }
if (exposed) {
// Damage Enemy! with a linear falloff of damage amount
var proximity : float = (location - enemy.transform.position).magnitude;
var effect : float = 1 - (proximity / radius);
enemy.ApplyDamage(damage * effect);
}
}
}
}
If you're using rigidbodies for your enemy objects, you could also use AddExplosionForce to add a proximity based force to push them away from the explosion centre.
I'm using a solution similar to this for explosions in a 2d game that I'm working on. I'm using a rocket of sorts that will detonate after a certain period of time, or when hitting walls/characters/ect. Upon hitting a surface, the explosion is formed. The explosion simply uses a circle collider which expands (rapidly, synced with a particle effect). When the explosion detects a collision with a character, before applying the damage and other effects, it throws a raycast that from the center of the explosion toward the detected player and checks against the high and low wall layers. If anything is found, the explosion is nullified.
This works really well.... I'm having one issue though... the rocket can often pass far enough into a wall so that the center is inside the wall, causing it to entirely block the explosion from all directions. The rocket is using continuous collision detection.. I was hoping enabling that would help.... but it didn't seem to solve the problem.
The only other solution I can think of is to come up with some cludgy way to have the explosion check if it's spawning inside a wall and push it slightly out along the shortest axis... or along an axis defined by the projectile's last and second to last positions.
Any advice?
Great, but I think enemyCollider should be enemy on the line that starts with exposed.
I know that this is really old but something to add here, and maybe there is a work around, but location - enemy.transform.position will always raycast towards the location of the transform, because the collision points from overlap sphere are always there; So if you have even the slightest barrier blocking the center of an object, then the raycast hits that even if the enemy is clearly exposed. Is there any way to get around that?
Answer by shankar_developer · May 28, 2011 at 06:40 AM
If you enable the Maximize on Play button in the Game window, the Game Window will expand when you hit play and get small again when you stop. The downside to this is that you can't see the inspector/hierarchy windows without opening them manually.
You are right in this aspect