Reputation: 85
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?
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
Reputation: 1069
If I understood corrently, you want to destroy barriers that collided with some kind of boundary?
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.
In this case, there are many approaches based on your game:
GameObject
with Rigidbody
component and add a script which would have OnTriggerEnter(...)
method and destroy colliding barriers in it.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
.Those are two that came up quickly in my mind.
Hope this helps!
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
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
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