- Home /
Checking if a collider is completly inside another collider using Bounds.Contains(): working only sometimes
First of all, I've a lot of threads about this. I think that my problem is more deep, so please keep reading.
I'm doing a 2D space game. Basically I have two GameObject: an asteroid and a black hole.
The asteroid gameobject has a Rigidbody 2D with body type "Dynamic" and a Capsule Collider 2D.
The black hole gameobject has a RigidBody 2D with body type "Kinematic" and a circle collider 2D, which surround the black hole body.
The black hole gameobject has a child gameobject called "Aura". It has Rigidbody2D with body type "Kinematic", a very large Circle Collider 2D and a Point Effector 2D.
The plan is as follows: when the asteroids is INSIDE the black hole, then it teleports to a random position. This is what it is doing, but only for the first time. That is after the first teleport the asteroid will not be able to do it again and it will get stuck in the center of the black hole.
Being more specific, I use OnTriggerStay2D() to check if the asteroid is colliding with the black hole body and another script ( called FullyContains() ) to check if it is actually completly inside.
Doing some console log, I noticed that everything is working during the first teleport, then the asteroid will not be able to teleport anymore because, even if OnTriggerStay2D() is called continously as intended, FullyContains() will always return false for some reason. That is only "CHECK IF THE ASTEROID IS ACTUALLY INSIDE" is logged.
The irony is that a "normal" asteroid is exactly identical to a teleported asteroid.
Another irony is that if I add one of OverTimeSizeChanger or SpriteFlash scripts, then "ONE OF THE TWO SCRIPTS DOES NOT EXIST" is logged.
The script that allows the teleport is inside the black hole body gameobject (not Aura) and is called teleportProcess().
I will post two version: - First one, it uses external scripts for fancy visual effects; - The second one, without using external scripts. Basically I tried to not attach my scripts to test if the problem was there, but the problem persists even when not using my scripts. If you are lazy, you can read it below below.
BlackHoleCollisionController.cs (Extended)
bool FullyContains(Collider2D resident)
{
Collider2D zone = GetComponent<Collider2D>();
return zone.bounds.Contains(resident.bounds.max) && zone.bounds.Contains(resident.bounds.min);
}
void OnTriggerStay2D(Collider2D other)
{
print("CHECK IF THE ASTEROID IS ACTUALLY INSIDE");
if (FullyContains(other))
{
print("THE ASTEROID IS INSIDE");
GameObject otherGameObject = other.gameObject;
StartCoroutine(teleportProcess(otherGameObject));
}
}
IEnumerator teleportProcess(GameObject otherGameObject)
{
print("TELEPORTING");
//
Collider2D asteroidCollider = otherGameObject.GetComponent<Collider2D>();
asteroidCollider.enabled = false;
print("COLLIDER DISABLED");
// These variables have to be not null
OverTimeSizeChanger externalOverTimeSizeChanger = null;
SpriteFlash externalSpriteFlash = null;
// Add needed scripts
if (otherGameObject.GetComponent("OverTimeSizeChanger") == null)
{
externalOverTimeSizeChanger = otherGameObject.AddComponent<OverTimeSizeChanger>();
}
if(otherGameObject.GetComponent("SpriteFlash") == null)
{
externalSpriteFlash = otherGameObject.AddComponent<SpriteFlash>();
}
print("externalOverTimeSizeChanger="+ externalOverTimeSizeChanger);
print("externalSpriteFlash="+ externalSpriteFlash);
if(externalOverTimeSizeChanger != null && externalSpriteFlash != null)
{
print("SCRIPTS ADDED TO THE ASTEROID. TIME TO ROCK!");
// Become smaller
float localScale = otherGameObject.transform.localScale.x;
StartCoroutine(externalOverTimeSizeChanger.changeSize(localScale, 0f, wayUpTravelDuration));
// Become black
yield return StartCoroutine(externalSpriteFlash.changeFlash(0f, 1f, wayUpTravelDuration, Color.black));
// Set velocity to 0 without losing the old velocity
Rigidbody2D rb = otherGameObject.GetComponent<Rigidbody2D>();
Vector2 oldVelocity = rb.velocity;
rb.velocity = new Vector2(0, 0);
// Stasis
Renderer renderer = otherGameObject.GetComponent<Renderer>();
renderer.enabled = false;
yield return new WaitForSeconds(stasisDuration);
// Teleport
otherGameObject.transform.position = getRandomPosition();
// Active GameObject
renderer.enabled = true;
// Become bigger
StartCoroutine(externalOverTimeSizeChanger.changeSize(0f, localScale, wayBackTravelDuration));
// Get colors again
yield return StartCoroutine(externalSpriteFlash.changeFlash(1f, 0f, wayBackTravelDuration, Color.white));
// Give the old velocity
rb.velocity = oldVelocity;
// Delete scripts
Destroy(externalSpriteFlash);
Destroy(externalOverTimeSizeChanger);
asteroidCollider.enabled = true;
print("COLLIDER ENABLED AGAIN");
} else
{
print("ONE OF THE TWO SCRIPTS DOES NOT EXIST");
}
print("--------------------------------");
}
IEnumerator teleportProcess(GameObject otherGameObject) (without using scripts)
IEnumerator teleportProcess(GameObject otherGameObject)
{
print("TELEPORTING");
//
Collider2D asteroidCollider = otherGameObject.GetComponent<Collider2D>();
asteroidCollider.enabled = false;
print("COLLIDER DISABLED");
print("TIME TO ROCK!");
// Set velocity to 0 without losing the old velocity
Rigidbody2D rb = otherGameObject.GetComponent<Rigidbody2D>();
Vector2 oldVelocity = rb.velocity;
rb.velocity = new Vector2(0, 0);
// Stasis
Renderer renderer = otherGameObject.GetComponent<Renderer>();
renderer.enabled = false;
yield return new WaitForSeconds(stasisDuration);
// Teleport
otherGameObject.transform.position = getRandomPosition();
// Active GameObject
renderer.enabled = true;
// Give the old velocity
rb.velocity = oldVelocity;
asteroidCollider.enabled = true;
print("COLLIDER ENABLED AGAIN");
print("--------------------------------");
}
Your answer