- Home /
ExplosiveForce Strange effects.
Hello i am attempting to make a rather realistic-ish explosion with a blast wave, I got it working but i am having some strange effects such as..
The force of the blast seem to be stronger when there are more rigid-body objects around But if it blows up with just 1 object it has little effect.
It is like its drawing energy from the surrounding objects to output a bigger blastwave.
Any ideas? here is my code. I have been doing tests in a 0 gravity space like environment. Thanks. Here is a web demo, Hopefully it will explain a little better
var expandRate = 10.0;
var radius = 0.0;
var power = 500.0;
var losePower = 250.0;
function Update () {
radius += expandRate * Time.deltaTime;
collider.radius = radius;
power -= losePower*Time.deltaTime;
}
function OnTriggerEnter (other : Collider) {
var explosionPos : Vector3 = transform.position;
var colliders : Collider[] = Physics.OverlapSphere (explosionPos, radius);
for (var hit : Collider in colliders) {
if (!hit)
continue;
if (hit.rigidbody && other.tag != "Bullet")
hit.rigidbody.AddExplosionForce(power, explosionPos, radius, 3.0);
}
}
Line 21 will make one explosion for each object it collides with. Try using break; or simply return; on line 22 after the first explosion happens.
Trying smaller radius could perhaps help. But I think it may be hard to get a consistent force hitting all object in a predictable manner using ExplosionForce. As the new explosions withh affect other close by rigidbodies.
Here is a web demo, Hopefully it will explain a little better
Answer by robertbu · Nov 03, 2014 at 10:25 PM
The problem is that you will deliver one application of force for every OnTriggerEnter(). The more objects, the more times OnTriggerEnter() is called. And your Update() function is also strange. It means the more time has passed since this object is created, the greater the range and the less the force. I'm not sure why you want this.
My suggestion is to get rid of the Update() code, and have the OnTriggerEnter() code either disable the script or destroy the object the script is attached to after it applies the explosive force once.
The update is the shock wave, the collier gets bigger over time like a wave would, but over distance it would lose its energy having a lower force. For example, If you throw a rock in a lake, the ripples it causes will only travel so far, The ripples will expand over time but the waves would get smaller.
I already tried to have it destroy the script / deactivate it but then it will only apply a force to the first object it hits.
Here is a web demo, Hopefully it will explain a little better
Cool idea. The error is still the same. You are applying force to all the collider in range for every trigger in the frame. $$anonymous$$ore new objects inside the collider, more trigger events. You can solve this in a couple of different ways. First you can put this at the top of the file:
private var frame = 0;
Then as the first two lines inside your OnTriggerEnter() function you can do:
if (frame == Time.frameCount) return;
frame = Time.frameCount;
This will cause the OnTriggerEnter() to only fire once per frame. You'll likely have to up the force you are adding to compensate.
As a second idea, consider getting rid of the Physics.OverlapSphere(). Then you can use AddExplosionForce() for each OnTriggerEnter() call in the frame. The effect will be different since only new colliders will be impacted each frame.
I decided to play a bit to see what I might do to get a shock wave effect. Here is what I came up with. Space bar start the explosion at the position of the game object with this script.
#pragma strict
var innerRadius = 0.0;
var outerRadius = 0.5;
var speed = 5.0;
var maxExplosionRadius = 5.0;
var explosionForce = 100.0;
private var exploding = false;
function Update () {
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space)) {
exploding = true;
}
if (!exploding) return;
var colliders = Physics.OverlapSphere(transform.position, outerRadius);
for (var col : Collider in colliders) {
if (Vector3.Distance(transform.position, col.transform.position) > innerRadius) {
col.rigidbody.AddExplosionForce(explosionForce, transform.position, maxExplosionRadius);
}
}
innerRadius += Time.deltaTime * speed;
outerRadius += Time.deltaTime * speed;
if (innerRadius > maxExplosionRadius) {
Destroy(gameObject);
}
}