- Home /
AddExplosionForce - what am i doing wrong
Can anyone spot what i'm doing wrong here please?
I've been running through the PushyPixels Space Invaders tutorial, and have hit an issue when adding explosion forces to the particles that are generated when you hit an Invader.
When the invader is hit, it loops through the 8 "gib" prefabs (attached to the enemy via the gibs public array in script) and instantiates each one and then applies the explosion force. But the particles aren't affected by the explosion force for some reason.
What's strange is that if i apply the explosion force after the instantiation loop using same params it works as expected (i used the example from the unity docs for this).
Here is the code:
public class GibOnCollide : MonoBehaviour
{
public GameObject[] gibs;
public float explosionForce;
public float spawnRadius = 1.0f;
void OnTriggerEnter()
{
foreach(GameObject gib in gibs)
{
GameObject gibInstance = Instantiate(gib, transform.position + Random.insideUnitSphere * spawnRadius, transform.rotation) as GameObject;
Rigidbody rb = gibInstance.GetComponent<Rigidbody>();
// this doesn't work for some reason!
// rb.AddExplosionForce(explosionForce, transform.position, spawnRadius);
}
Collider[] hitColliders = Physics.OverlapSphere(transform.position, spawnRadius);
foreach (Collider hit in hitColliders)
{
Rigidbody rb = hit.GetComponent<Rigidbody>();
if (rb != null)
{
// this does work!!
rb.AddExplosionForce(explosionForce, transform.position, spawnRadius);
}
}
Destroy(gameObject);
}
}
I've checked the gib prefab and it has the Rigidbody component attached and is not set as Kinematic.
I'm using Unity 2017.2 BTW.
Thanks, Alan
Hi @jchester07,
I added debug message to check rb and it wasn't null.
I've done some more testing and i can get it to work if i call AddExplosionForce via a coroutine and add a small delay:
IEnumerator delayedExplosion(Rigidbody rb)
{
Debug.Log("Coroutine called");
yield return new WaitForSeconds(0.000001f);
Debug.Log("Finished waiting adding explision force now!");
rb.AddExplosionForce(explosionForce, transform.position, spawnRadius);
}
void OnTriggerEnter()
{
foreach (GameObject gib in gibs)
{
GameObject gibInstance = Instantiate(gib, transform.position + Random.insideUnitSphere * spawnRadius, transform.rotation) as GameObject;
Rigidbody rb = gibInstance.GetComponent<Rigidbody>();
// this only works if called via a coroutine
StartCoroutine(delayedExplosion(rb));
// this doesn't work for some reason!
//rb.AddExplosionForce(explosionForce, transform.position, spawnRadius);
}
Out of curiosity I tried putting a delay directly in the instantiation loop but that didn't work, so it's as if the system needs to move forward a frame or 2 before you can use the AddExplosionForce function.
Has anyone else experienced this, is it normal?
Thanks, Alan
I tried your original script and its working on my end. Can you try testing it on a new project? There must be other factors affecting it beside the script alone.
Hi @jchester07,
O$$anonymous$$, i created a new project to try and re-create the issue.
I've simplified it, there is one "Spawner" object. When press the space key it spawns 4 cubes randomly around the Spawner. For each cube it adds explosion force, with the explosion position being set as the the Spawner position.
So, when i apply explosion force immediately after instantiating the cube the cube gets forced upwards only:
If i change it so that the explosion force is applied shortly after it is instantiated, however, it looks (to me at least) more correct:
Below is the script i'm using in the new project:
public class SpawnCubes : $$anonymous$$onoBehaviour
{
public GameObject[] cubes;
public float spawnRadius;
public float explosionForce;
IEnumerator delayedExplosion(Rigidbody rb)
{
yield return new WaitForSeconds(0.01f);
rb.AddExplosionForce(explosionForce, transform.position, spawnRadius);
}
// Update is called once per frame
void Update()
{
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space))
{
foreach (GameObject cube in cubes)
{
GameObject cubeInstance = Instantiate(cube, transform.position + Random.insideUnitSphere * spawnRadius, transform.rotation);
Rigidbody rb = cubeInstance.GetComponent<Rigidbody>();
// the following doesn't appear to correctly add the explosion force (all of the cubes just go straight up)
// if ins$$anonymous$$d you comment this line out and uncomment the one below it (StartCoroutine(delayedExplosion(rb)); that seems to work fine)
// it's as if the AddExplosionForce doesn't work if run immediately after creating the instance
rb.AddExplosionForce(explosionForce, transform.position, spawnRadius);
//StartCoroutine(delayedExplosion(rb));
}
}
}
}
FYI - here are the Spawner properties:
And the SmallCube properties: