- Home /
Trying to Create Bomb Power Up - Almost there?
Hi
I'm trying to create a power up designed to explode destroying everything in the blast area. Using Physics.Overlapshere I am attempting to create an array of all the colliders in the blast zone. Then I'm trying to access the objects assigned to that collider and then to access the objects attached script 'DestroyByContact' which I then hope to call the public function 'Destroyed'.
I don't think I'm far off finishing but I think I need a bit of help with accessing objects on the colliders thing.
I think I have included everything that I'm working with here. Shout out if not. :) Any help would be great please. Cheers :)
My code
Bomb script (as you can probably see, I get lost once I get into the code following 'if (col.collider.tag' ) :/
public class Bomb : MonoBehaviour
{
public Transform explosionPosition = transform.position;
public float explosionRadius = 10.0;
public Collider[] colliders = Physics.OverlapSphere(explosionPosition, explosionRadius);
private GameObject victim;
void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
Destroy(gameObject);
Explode();
}
else
{
return;
}
}
void Explode()
{
foreach (Collider col in colliders)
{
if (col.collider.tag == "LargeHazard" | col.collider.tag == "MediumHazard" | col.collider.tag == "Hazard")
{
//Destroy(col.collider.gameObject);
GameObject victimObject = Collider.gameObject;
victim = victimObject.GetComponent<DestroyByContact>();
victim.Destroyed();
}
}
}
}
DestroyByContact (I've only included the function I want to call)
public void Destroyed()
{
gameController.AddScore(scoreValue);
}
Does this work?
public Collider[] colliders = Physics.OverlapSphere(explosionPosition, explosionRadius);
i thing it should be on trigger enter. Whats you result so far?
Answer by Baste · Sep 25, 2014 at 01:12 PM
There's a couple of problems here:
1: You declare the colliders array as a field, meaning that this code:
public Collider[] colliders = Physics.OverlapSphere(explosionPosition, explosionRadius);
Will be called once, when the object is generated. You need to put that line inside the explode method:
void Explode()
{
Collider[] colliders = Physics.OverlapSphere(explosionPosition, explosionRadius);
foreach (Collider col in colliders)
{ ...
2: This can't possibly compile:
GameObject victimObject = Collider.gameObject;
victim = victimObject.GetComponent<DestroyByContact>();
victim.Destroyed();
Victim is declared as a GameObject further up, so the Destroyed-method won't be available, as it's not a GameObject-method. Victim needs to be declared as a DestroyByContact, and you should only have it available within the Explode method. Remove "private GameObject victim" from your fields, and declare it locally in the Explode method as a DestroyByContact like this:
GameObject victimObject = Collider.gameObject;
DestroyByContact victim = victimObject.GetComponent<DestroyByContact>();
victim.Destroyed();
That should make your code work!
3: As an additional protip; generally I'd recommend against using tags, and instead checking for what scripts are on the object. Tags are generally a mess, and if you mess up and forget to put one in, stuff won't work for no particularly clear reason. After your project has grown a bit, changing the names of tags will also become near impossible, as there's no easy way to check what scripts are checking for what tags. In my opinion, a better way to do your Explode method would be:
foreach (Collider col in colliders)
{
GameObject victimObject = Collider.gameObject;
DestroyByContact victim = victimObject.GetComponent<DestroyByContact>();
//Check if the DestroyByContact script actually exists
if(victim != null)
victim.Destroyed();
}
Wow thanks a lot for that. Some great stuff there which I will practice.
It had reduced the amount of errors and I fixed all but one which I'm not sure of. I think i know whats its getting at but I couldn't be sure that its already been done. This error: error CS0120: An object reference is required to access non-static member, appears for this line:
GameObject victimObject = Collider.gameObject;
I know you'v helped me a lot already @baste :)
That's because you are saying Collider.gameObject();
That will reference the class called Collider, and because a class is not an object, you get the error. You should change that to col.gameObject();
By doing that, you are referencing the GameObject which the current collider from the array is attached to.
That should be it, good luck!
/TheDDestroyer12
Cheers destroyer.
The code gets as far as the if statement inside foreach before stopping. Tried it with my tag if statement and Baste's if(victim != null)
but it doesn't get past the if statement. If I take the if statement out I just get a NullReferenceException error for victim.Destroyed();
. The reference isn't being made properly for the DestroyByContact but I can't see why. :(
void Explode()
{
Debug.Log ("(Explode Called)");
Vector3 explosionPosition = transform.position;
Collider[] colliders = Physics.OverlapSphere(explosionPosition, explosionRadius);
foreach (Collider col in colliders)
{
GameObject victimObject = col.gameObject;
DestroyByContact victim = victimObject.GetComponent<DestroyByContact>();
Debug.Log ("before null)");
if(victim != null)
{
victim.Destroyed();
Debug.Log ("Victim destroyed called)"); //if game object isn't found message will show
}
}
The nullreference is due to the script being called on every object that's collided with - including stuff like the ground and stuff. That's why the null-check is there; if GetComponent doesn't find a component of the correct type, it returns null.
If you have the null-check in, and victim.Destroyed is never called, it means that there's no objects (with colliders on them) within the overlap sphere that has the DestroyByContact script attached to them.
That makes sense. It's a small space game so in theory the only colliders it should meet is players and enemies. All enemies have the DestroyByContact script on them but what did cross my $$anonymous$$d was that the colliders are on the child object whereas the script is on parent. I wouldn't have thought this would make a difference though.
I don't see why it is returning null. Is there anything else that I might have missed by any chance @Baste?
Just put this Debug.Log (colliders.Length);
in after the OverlapShere and it returns 3 colliders which is correct. 1 of those colliders has DestroyByContact script on that game object.