Destroy gameobjects several times in a scene. Also destroy other instances of that gameobject.
So this is my ball and two blue walls.
I use
bw = GameObject.FindWithTag("bw");
private void Explosion (){
if (radius.Contains (bw)) {
Destroy (bw);
}
}
private void OnTriggerEnter(Collider col){
radius.Add(col.gameObject);
}
private void OnTriggerExit (Collider col){
radius.Remove(col.gameObject);
}
So each time one of the walls get into the range of "col" they should be added to the list "radius" and when the ball move too far away they should be removed from the list and not therefore not destroyed when Explosion is run.
This works for BW1 but when I reach BW2 I reach BW2 i get an null error, saying that I'm trying to access a gameobject I already destroyed. I've dragged them both into the scene from a prefab I created earlier if that matters, they are both tagged with "bw". Also, if I reach BW2 first I won't get the error but neither will it destroy that wall.
So my questions would be:
How can I remove BW1 from the scene without destroying the gameobject so that I can remove additional BWs later? (or destroy the gameobject as long as I can do it on several BWs)
How can I remove BW2? since the code I have doesn't seem to affect it.
Thank you very much!
Answer by LiloE · Mar 29, 2017 at 05:13 PM
There are several conceptual/design problems with your code, as far as we can see from what you shared.
This expression:
GameObject.FindWithTag("bw");
will return a single object tagged "bw". But it is not guaranteed to be any specific object in any specific order.You can use
GameObject.FindGameObjectsWithTag("bw");
instead, which is better, but this brings us to the next design problem - why are you looking for these objects in the first place? You already have them in yourradius
collection, and judging by your logic - you're only interested in those that are already in that collection. So, why not just iterate through the collection and destroy those elements instead?Destroying the objects isn't enough, you also need to remove the object from the radius container, otherwise, next time you run the explosion, the game engine will attempt to destroy those objects again.
Using SetActive instead of actually destroying is indeed better for the general performance of the game. Regarding the timing you need for this function - try something like this:
using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { void Hide(float timeToWait) { Invoke("HideMe", timeToWait); } void HideMe() { gameObject.SetActive(false); } }
Thank you very much! I'm new to this, I apologize for all the obvious errors and now follow-up questions.
I was using bw to show the problem that I only manage to destroy one wall. I have walls in four different colors and that's why I thought I needed the different tags to be able to destroy the correct one. To destroy them I have an area on the screen which activates an "explosion" associated with respective color.
Can I find the correct color somehow within the radius (since sometimes it might be more than one color in the radius) and destroy it from there, without the GameObject.FindGameObjectsWithTag("color for each obstacle");
? Since I don't always want to destroy them when they are in the radius, unless the correct explosion is activated it shouldn't be removed.
Regarding removing the objects from radius I thought private void OnTriggerExit (Collider col){ radius.Remove(col.gameObject);}
would do that? Does this not work when I use Destroy? Will SetActive(false); fix that in that case or do I still need to find another solution to removing them?
I've changed to
public GameObject[] bw;
bw = GameObject.FindGameObjectsWithTag("bw");
so now I can check
private void Explosion (){
for(int i=0; i < bw.Length; i++){
if (radius.Contains (bw[i])) {
bw[i].setActive(false);
}
}
}
But when I try to use the hide method I can't get it to work on bw[i] and I can only get the bw[0] particlesystem to go off. Do I need to assign all other PS in the unity inspector or is it possible to activate them completely from the script?
Thank you very much!
Answer by herDev · Mar 27, 2017 at 08:43 AM
Hi,
So I'm assuming 'col' is your ball. If it's not already on it, you could add your collision script to this gameobject and then you can get a reference to the other 'wall' object from the 2Dcollision method (otherObject is automatically assigned) and add it a list or do whatever you want to do with it:
void OnCollisionEnter2D(Collision2D otherObject)
{
radius.Add(otherObject);
}
private void OnCollisionExit2D(Collision2D otherObject)
{
radius.Remove(otherObject);
}
ps. you'll need to set up the rigidbody's correctly too (isKinematic values etc). Also rather than destroying them, use SetActive(false) so garbage collection doesnt kick in.
Hope that helps!
The code you've written is the only thing I said that works with my code. Sorry if I didn't specify, the game is in 3d.
SetActive might work but I have a particlesystem on my BWs now. With destroy I have a delay which allows me to play this PS, but with SetActive there isn't a delay parameter. How do I solve that? Or is there a better way to do this without any of the previous functions?