- Home /
Collision between two instances of the same object
Hello! I'm creating a building game where the player should not be able to place buildings on top of each other. Each time a new building is selected and placed, it is instantiated only if there is no building already there.
In order to do this, I attached a BoxCollider & RigidBody component to the building prefabs, and written a script that uses OnCollisionEnter to check for collisions (also attached to the prefabs). I've read through much documentation and forum posts, I simply cannot get the collisions working. Please take a look at my screenshots & code, if you can find where I'm making a mistake I'd be eternally grateful.
1. Screenshot of the farm prefab in the inspector.
2. BuildingCollisions.cs - Checks if any collisions occur (if a building already exists in that spot)
public class BuildingCollisions : MonoBehaviour{
void Update(){
collisionDetection();
}
public bool collisionDetection(){
RaycastHit hit;
if (Physics.Raycast(transform.position, -Vector3.up, out hit, 3)){
if (hit.collider.gameObject.CompareTag("Building")){
Debug.Log("A building is already there!");
return true;
}else{
return false;
}
}else{
return false;
}
}
}
3. Farm.cs - Instantiates a farm (only relevant function shown)
void moveFarm(){
// The position of the mouse in screen coordinates
Vector3 screenPos = Input.mousePosition;
screenPos.z = 225;
// The position of the mouse in world coordinates
Vector3 worldPos = myCamera.ScreenToWorldPoint(screenPos);
// Update the farm's position
if (farmPlacep == false){
farm.transform.position = worldPos;
}
// When the user left clicks...
if (Input.GetMouseButtonDown(0)){
// Instantiate BuildingCollisions class
BuildingCollisions getBuildingCollisions;
getBuildingCollisions = gameObject.AddComponent("BuildingCollisions") as BuildingCollisions;
Debug.Log("Building already there?: " + getBuildingCollisions.collisionDetection());
// Only if a building collision isn't occurring, build the farm
if (getBuildingCollisions.collisionDetection() == false){
Instantiate(farm, worldPos, Quaternion.identity);
farmPlacep = true;
farmSelectedp = false;
}
}
}
Do you have CharacterController on your player or rigidbody ? if the player is a CharacterController, try use OnControllerColliderHit. OnCollision event are triggered when a rigidbody hits a CharacterController.
No, there's no player object or character controller. This is a SimCity type game, so the player is placing buildings from a birds-eye view, or "God mode" view.
So wait, OnCollisionEnter & OnCollisionStay are only triggered when one of the objects is a CharacterController?
Given that this is a non-moving game, rather than colliders, use raycasts. You can raycast to the position you are about to place the building and take a look at the hit.
I think the problem is that you are checking for the result before the physics update. (And if you don't have a rigidbody, that will also be a problem)
@robertbu has the answer. Just raycast to check first, or maintain a separate list of what is in each square
Yes. They happen between Update()s (depending on framerate, you might not get one between 2 Updates, or you might get many)
But you don't yield to allow a FixedUpdate() to occur between instantiating and checking. I may be wrong, but I believe that will not allow the OnCollissionEnter to run until after you've checked
Answer by whydoidoit · Mar 19, 2013 at 01:53 PM
Rigidbodies that don't move often go to sleep, which can be a problem. But I'd have thought your underlying requirement is that at a moment in time you want to check if something is at a particular location - you can do that with:
Raycast - if your building are laid out on a grid you'd only need one
Ok, thank you very much. I'll be implementing Raycasting later today and see if that works.
Hello, so I implemented Raycasting and there are still problems. See the original post for the updated code.
The output:
When I place a farm, and then hover over the built farm with another farm the console prints "A building is already there!" as it supposed to. Unfortunately, it still lets me place it on top of the first farm.
Additionally, even though it prints the Building Already There warning, it also prints "Building already there?: false" when it should be true.
A raycast starting within a collider won't hit it. Perhaps you should be doing -Vector3.up * 100 and making you raycast 100 long?
Been wicked busy lately, finally got to try out
Physics.Raycast(transform.position, -Vector3.up * 100, out hit, 100)
It didn't change anything, same problem. Prints "A building is already there!" but still lets me place it. scratches head any ideas?
That should be:
Physics.Raycast(transform.position -Vector3.up * 100, Vector3.down, out hit, 100)
Perhaps you could edit the question and post the code again if that doesn't help?
Your answer
Follow this Question
Related Questions
Collision between two instances of the same object 1 Answer
Making a turret fire another arrow if an enemy survives the hit 3 Answers
Lightswitch help? 3 Answers
OnCollisionEnter not triggering when two rigidbody collide via Instantiate 1 Answer
How do i destroy only 1 object when 2 instances of the same object collide ? 2 Answers