- Home /
Deleting objects when they overlap other objects?
Alrighty I have seriously tried everything, and I keep asking little questions to try to figure this out, but each solution seems to lead to another even worse problem. So I figured I should just ask the big question. I am trying to make it so that when this object is instantiated, it makes sure it isn't touching any other objects. If it is, then it deletes itself. If it isn't, then it marks itself as instantiated in another script and then the script disables itself. And I have this all happening in the update function so that it continuously checks in case two objects instantiate at the same moment. This is the script:
using UnityEngine;
using System.Collections;
public class AfterInstantiation : MonoBehaviour {
public float radius = 0.1f;
private GameObject control;
private GameManager manager;
private bool overlapping = true;
private GameObject overlapper;
private Bounds bounds1;
private Collider[] hitColliders;
private Collider hitCollider2;
private Collider hitCollider3;
private Collider hitCollider4;
private Collider hitCollider5;
private Bounds bounds2;
private Bounds bounds3;
private Bounds bounds4;
private Bounds bounds5;
private GameObject bounds2GameObject;
private GameObject bounds3GameObject;
private GameObject bounds4GameObject;
private GameObject bounds5GameObject;
private bool scriptDisabled = false;
void Update(){
bounds1 = gameObject.renderer.bounds;
hitColliders = Physics.OverlapSphere(transform.position, bounds1.extents.magnitude);
hitCollider2 = hitColliders[0];
bounds2GameObject = hitCollider2.gameObject;
bounds2 = bounds2GameObject.renderer.bounds;
hitCollider3 = hitColliders[1];
bounds3GameObject = hitCollider3.gameObject;
bounds3 = bounds2GameObject.renderer.bounds;
hitCollider4 = hitColliders[2];
bounds4GameObject = hitCollider4.gameObject;
bounds4 = bounds2GameObject.renderer.bounds;
hitCollider5 = hitColliders[3];
bounds5GameObject = hitCollider5.gameObject;
bounds5 = bounds2GameObject.renderer.bounds;
if (!bounds1.Intersects (bounds2) || !bounds1.Intersects (bounds3) || !bounds1.Intersects (bounds4) || !bounds1.Intersects (bounds5)){
Debug.Log ("Destroying " + gameObject);
Destroy (gameObject);
}
else {
MarkAsInstantiated ();
}
if (scriptDisabled){
enabled = false;
}
}
void MarkAsInstantiated(){
control = GameObject.FindGameObjectWithTag ("Manager");
manager = control.GetComponent <GameManager> ();
GameManager.dungeonsExisting += 1;
scriptDisabled = true;
}
}
The script has no errors or anything, so the problem probably has something to do with how inefficient my code is. Either way, when I run the game, I still get all sorts of objects spawning on top of each other, which is what this script is supposed to prevent. I have tried for two days to figure this script out, but I just haven't been able to. Maybe somebody with more brains than me can see what I'm doing wrong? Thanks in advance for any help.
Edit:
yeah I know my code's a mess, I've been messing around with it so much and I haven't cleaned it up yet.
Are you ever hitting your destroy? Have you verified there are only ever 4 hit colliders?
It hits the destroy, because the Debug there works. And there might be more than 4, but I made it 10 and the results were basically the same (i can't say exactly the same because it is random generation). This is why this problem sucks so much.
Answer by KellyThomas · Jan 12, 2014 at 12:43 AM
I would get rid of the something1...something4 approach it will fail to scale up or down when things change.
The condition "`if (!bounds1.Intersects (bounds2) ||...`" if evaluate to true if any
Intesects()
call returns false.Are you sure this should be in
Update()
? It seams like a good fit forStart()
orAwake()
.You find the
GameManager
instance but then access a static member.
Here is an implantation that address these points:
using UnityEngine;
using System.Collections;
public class AfterInstantiation : MonoBehaviour {
void Start(){
bool overlapping = false;
Bounds bounds = renderer.bounds;
Collider[] hitColliders; = Physics.OverlapSphere(transform.position, bounds.extents.magnitude);
foreach(Collider col in hitColliders) {
GameObject other = col.gameObject;
if (other == gameObject) {
continue;
}
if (bounds.Intersects(other.renderer.bounds)) {
overlapping = true;
break;
}
}
if (overlapping){
Debug.Log ("Destroying " + gameObject);
Destroy (gameObject);
enabled = false;
}
else {
Debug.Log ("Keeping" + gameObject);
MarkAsInstantiated ();
}
}
void MarkAsInstantiated(){
GameManager.dungeonsExisting += 1;
}
}
However to keep everything harmonious in the long term I think that this check should be made back in the Manager
while it is building the dungeon, rather than by each dungeon room.
Assuming the GameManager
is keeping track of the known good dungeon pieces then it should be be able to perform a check like this on each new candidate:
bool IsOverlapping(GameObject candidate, GameObject[] others) {
foreach(GameObject other in others) {
if (candidate.renderer.bounds.Intersects(other.renderer.bounds)) {
return true;
}
}
return false;
}
Okay, you are my favorite person in the world right now. I have no doubt this will work, and you've helped me out with this problem twice. Ima go ahead and mark this as answered, but I do have a question. On line 14, it doesn't seem to recognize next. It tells me
Only assignment, call, increment, decrement, and new object expressions can be used as a statement
As I have said I'm new to scripting, but I assume the next is supposed to make it move on to the next collider it hit, so continue or break wouldn't work right? Any ideas?
Thanks so much again.
Edit:
Yes I originally had it in the Start function but I changed it because I thought the reason for overlapping might have been that some of the objects were spawning at the same moment.
Sorry, my bad:
c# uses continue
to jump to the next iteration.
I tried continue, but when I push play it deletes the very first dungeon and the map is left blank... haha I hate to keep asking since you've helped so much, please don't feel obligated to answer if it's too complicated. I will probably figure it out eventually :P
If that is occurring it means that one of the intersects calls is returning true, even on the first piece.
You can try adding something like this debug line to investigate which object is causing the problem.
if (bounds.Intersects(other.renderer.bounds)) {
overlapping = true;
Debug.Log("Overlapping with: " + other);
break;
}
Oh I'm an idiot! It's hitting the player! Hahaha thank you so much, you just made me so happy.