- Home /
Destroying an instantiated object colliding with another instantiated object
Broad question: How do you destroy an instantiated object if it's instantiated in a position that makes it collide with another objected generated by the same script?
Specific situation: So I'm procedurally generating a forest with 2 kinds of trees (flufftrees and short flufftrees - there will be more types later if I can figure this out!). Here is the C# code that generates them:
using UnityEngine;
using System.Collections;
public class TreeSeeder : MonoBehaviour {
public int flufftreecount;
public int shortfluffcount;
public int randposmin;
public int randposmax;
public Rigidbody flufftree;
public Rigidbody flufftree_short;
// Use this for initialization
void Start () {
//Making flufftrees
for (int i=0; i < flufftreecount; i++){
//random coordinates generated
int randpos = 3 * Random.Range(randposmin, randposmax);
int randpos2 = 3 * Random.Range(randposmin, randposmax);
int randrot = Random.Range(1,359);
//parse into position
Vector3 flufftreepos = new Vector3(randpos, 0, randpos2);
//instantiate object at random coordinates
Rigidbody flufftree_child = Instantiate(flufftree, flufftreepos, Quaternion.identity) as Rigidbody;
flufftree_child.transform.rotation = Quaternion.Euler(0,randrot,0);
flufftree_child.tag = "Nature";
yield return null;
// Removing if intersecting other Nature objects
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Nature" )
{
Destroy(col.gameObject);
}
}
}
//making shortfluffs
for (int j=0; j < shortfluffcount; j++){
//random coordinates generated
int randpos = 3 * Random.Range(randposmin, randposmax);
int randpos2 = 3 * Random.Range(randposmin, randposmax);
int randrot = Random.Range(0,360);
//parse into position
Vector3 shortfluffpos = new Vector3(randpos, 0, randpos2);
//instantiate object at random coordinates
Rigidbody shortfluff_child = Instantiate(flufftree_short, shortfluffpos, Quaternion.identity) as Rigidbody;
shortfluff_child.transform.rotation = Quaternion.Euler(0,randrot,0);
shortfluff_child.tag = "Nature";
yield return null;
// Removing if intersecting other Nature objects
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Nature")
{
Destroy(col.gameObject);
}
}
}
}
// Update is called once per frame
void Update () {
}
}
My problem: I need to destroy any trees which are generated in space already occupied by another tree. I thought that sections of code like this would do that, but they seem to have no impact on the situation:
// Removing if intersecting other Nature objects
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Nature")
{
Destroy(col.gameObject);
}
I also included yields before these sections to allow a frame to pass before the script checks for collisions with other "Nature" tagged trees (all trees will have this tag). But alas, no luck.
I think I have the right idea here... what am I doing wrong?
Did you try debugging the col.gameobject to see if its actually having a collision? Your collision script should be on the tree. You can also try the OnTriggerEnter() approach. I've had more success with triggers ins$$anonymous$$d of collisions.
A more viable solution would be to shoot a ray at the location to check if another tree is there. And if it is, then don't spawn in another tree.
Is this possible to put one method inside another method???? Or I am missing some coding basis????????
Do you mean check "is kinematic" on the empty game object this script is attached to or assign the property "is kinematic" to the instantiated object in the script? How would you do that in the script? I put the collision method in Start because I just want to check when the tree is instantiated (once).
Answer by ProtoTerminator · Jun 19, 2014 at 03:06 AM
Unity for some reason doesn't detect collisions with objects that aren't moving. To get around this you need to put a rigidbody on your objects and check Is Kinematic. That should fix that problem. I'm not sure how expensive rigidbodies will be, but you should be able to just remove the rigidbody via script after instantiation if it becomes a problem.
Also, you'll need to be careful with this approach, as it's very easy to destroy both trees (the collision will be called on both of them).
Also, looking at your code more, I'm not sure what putting a collision method inside the start method does. I usually put the collision methods on a separate script that I attach directly to the gameobject prefab.
Use can use OverLapSphere to check for other objects within the bounds of another.
There are other ways too, but I forget those for the moment.
Adding the kinematic rigidbody component to the prefab has no effect... same problem as before :/
Answer by Ricewind1 · Jun 19, 2014 at 11:13 AM
You could create a mini collision script and add it to both trees when they are instantiated. This way you'll be sure to only destroy the one triggering the collision event. You can even let this code generate automatically so that it's re-usable by other instances (namely the if(tag=tree) part.
@ricewind1 this was what I was trying to do but it doesn't work. Adding it to the prefabs doesn't work either.
It doesn't remove intersecting trees. Applying this script to the prefabs didn't destroy them either.
Answer by DarKTower · Jun 20, 2014 at 12:31 AM
Here's a quick solution I thought up in my head, but have no idea if it would work or not:
Make sure both tree Prefabs' Rigidbodies are NOT Kinematic.
Instantiate the trees
Instead of checking for OnCollisionEnter (Which, to my knowledge, is only called when a Collider enters another Collider through force, not by Instantiating).
Check for OnCollisionStay instead.
If there is a OnCollisionStay detected, destroy one of the objects (Whichever you want to destroy)
If there is NOT an OnCollisionStay detection (By either a WaitForSeconds yield or another method of your choosing), set the Rigidbody of the object to be Kinematic.
Go on your merry way.
OnCollisionStay only works when one is not Kinematic, thus the reason for setting it to Kinematic afterwards. OnCollisionStay is also called even when an object is Instantiated inside another object (At least I believe it is), which OnCollisionEnter is not.
Good luck!