Don_Huan
Don_Huan

Reputation: 85

Delete spawning list objects consistently

Already 2 days I'm trying to solve this problem but I can't.I'm trying to delete the unlimited spawning barriers consistently when they are collide with the boundary.The barriers are made from 5 cubes.Any ideas?

enter image description here

enter image description here

enter image description here

public List<GameObject> spawning=new List<GameObject>();
public Vector3[] positions = new Vector3[5];

public GameObject barrier;
public GameObject boundary;


void Start()
{
StartCoroutine (SpawnBarrier());
}

void Update()
{
if(true)
{
    foreach (GameObject move in spawning) 
        move.transform.Translate (0f, 0f, -0.1f);
}

}


IEnumerator SpawnBarrier(){

yield return new WaitForSeconds (3f);

while (true) {


    for(int i=0;i<=4;i++)
    {

        spawning.Add (Instantiate (barrier, positions [i],   Quaternion.identity)as GameObject);



    }
    yield return new WaitForSeconds (3f);

}
}

Upvotes: 0

Views: 121

Answers (3)

tsvedas
tsvedas

Reputation: 1069

If I understood corrently, you want to destroy barriers that collided with some kind of boundary?

If the 'boundary' is the visible screen space

In this case, we can assume that, once the object is invisible to MainCamera it can be counted as out of the boundary. Keeping that in mind, we can use OnBecameInvisible() method, which is method (or message, as stated in Unity Scripting API) called by MonoBehaviour class:

// A piece of barrier that gets destroyed once out of screen
public sealed class BarrierPiece : MonoBehaviour
{
    // Called once the object is no longer visible to any (scene editor included) camera
    private void OnBecameInvisible()
    {
        Destroy(gameObject);
    }
}

NOTE: if you have more than one Camera in your scene, the object must be invisible to all of the cameras in order for the OnBecameInvisible() to be called.

If the 'boundary' is other object

In this case, there are many approaches based on your game:

  • Create GameObject with Rigidbody component and add a script which would have OnTriggerEnter(...) method and destroy colliding barriers in it.
  • (Inefficient) have two static Vector2 variables, one for pivotPosition, other for maximumOffset (this one should be squared for faster calculations). Then, have script on each of the barriers and in Update() checks whether the object's squared distance to the pivotPosition is greater than maximumOffset and call Destroy(gameObject) if the condition is true.
  • (others) ...

Those are two that came up quickly in my mind.

Hope this helps!

EDIT

Didn't look at the images...

So for your solution, you would need to assign Rigidbody component to the Boundary and add BoxCollider component on all of the barriers. Now, create a tag, called Barrier and tag all the barriers with it. Create a script:

// Destroys barriers on collision
public sealed class BarrierBoundary : MonoBehaviour
{
    // Called once the script is created
    // Checks if the object has Rigidbody component attached
    private void Awake()
    {
        Debug.Assert(GetComponent<Rigidbody>() != null);
    }

    private void OnCollisionEnter(Collision collision)
    {
        if(collision.collider.tag == "Barrier")
            Destroy(collision.collider.gameObject);
    }
}

(The code wasn't tested, so it can have some typos.)

Now, assign the script to the Boundary. And voila! Barriers are destroyed once hitting the boundary.
Hope (again) this helps!

Upvotes: 0

Programmer
Programmer

Reputation: 125275

Your barriers are marked as isTrigger on their colliders therefore you can use OnTriggerEnter to detect when any of the barriers collides with the boundary.

You need to create new script, lets call that BoundaryDetector and attach it to the barrier prefab so that every instance of the barrier will have this script attached to it.

When OnTriggerEnter is called, check if the trigger is made by the boundary. This can be done by checking for the "Player" tag since boundary is tagged as Player in your screenshot. If the detected trigger tag is "Player", first remove the spawning from the spawning List then Destroy it.

The BoundaryDetector script is as below (Must be attached to the barrier prefab):

ScriptFromYourQuestion yourInstancingSript;

void Start()
{
    GameObject obj = GameObject.Find("NameOfObjectScriptInYourQuestionIsAttachedTo");
    yourInstancingSript = obj.GetComponent<ScriptFromYourQuestion>();
}


void OnTriggerEnter(Collider other)
{
    //Detect if we collided with the boundary
    if (other.CompareTag("Player"))
    {
        //Remove Self/barrier from the List
        yourInstancingSript.spawning.Remove(this.gameObject);


        //Delete Self/barrier 
        Destroy(this.gameObject);
    }
}

Note: The ScriptFromYourQuestion should be replaced with the name of the script in your question.

MUST DO:

To get the code above working, the following changes must be made in the Update function of the script from your question:

1.You must attach Rigidbody to at-least one of the Objects (boundary or barrier). In this case, I suggest you do so to the barrier prefab.

2.You must remove move.transform.Translate (0f, 0f, -0.1f); and replace it with Rigidbody.MovePosition and use that to move your barries because you have now attached Rigidbody to your barries and this is the proper way to move a Rigidbody Object.

Maybe something like this:

Your Update function in the code form your quesion should looks something like this:

public float speed = 100.0f;

void Update()
{
    if (true)
    {
        foreach (GameObject move in spawning)
        {
            //Get Rigidbody component 
            Rigidbody rb = move.GetComponent<Rigidbody>();
            //Calculate Z-axis pos to move to
            Vector3 pos = new Vector3(0, 0, 1);
            pos = pos.normalized * speed * Time.deltaTime;
            //Move with Rigidbody
            rb.MovePosition(rb.transform.position + pos);
        }
    }
}

Upvotes: 1

Dan
Dan

Reputation: 537

Your problem is that you have an infinite loop while true that you're not breaking out of. Instead you should add a counter. You haven't explained what you want to do but my example is that it will breakout once it completes 10 instantiations of 5 blocks.

IEnumerator SpawnBarrier(){
    spawnCount=0
    yield return new WaitForSeconds (3f);
    while (true) {
        for(int i=0;i<=4;i++)
        {
            spawning.Add (Instantiate (barrier, positions [i],   Quaternion.identity)as GameObject);
        }
        if (++spawnCount==10)
        {
            break;
        }
        yield return new WaitForSeconds (3f);
    }
}

Upvotes: 0

Related Questions