Mysterious behavior with Instantiate + Raycast

Project is attached.

  • I want to spawn randomly 60 cubes in a small area.
  • I test if the randomly generated position is available (no collision with other cubes). If not, I keep generating new positions.
  • I Instantiate the cube before anything else, so that I can use its bounds to calculate 4 points to use with Raycast.

The problem is that the Raycast calls do not work unless the instantiated cube is deactivated!

You can check this behavior playing with the disableNewGameObject boolean in the script.
Its very easy to understand if you check the project.

Can someone explain this?

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class InstantiateBug : MonoBehaviour {
	
	public static float WIDTH = 100;
	public static float HEIGHT = 300;
		
	public GameObject cubePrefab;
	
	public bool disableNewGameObject = false;
	
	void Start() {
		
		Setup();
	}
	
	public void Setup() {
		
		// add cubes
		int numCubesToAdd = 60;
		
		for(int i = 0; i < numCubesToAdd; i++) {
			
			SpawnCube();
		}
	}
	
	void SpawnCube() {
		
		// spawn a cube inside the area(WIDTH x HEIGHT)
		
		GameObject newGO = (GameObject)GameObject.Instantiate(cubePrefab);
			
		Bounds bounds = newGO.collider.bounds;
		if(disableNewGameObject) {
			newGO.SetActiveRecursively(false);
		}
		
		Vector3 newPos;
		bool colliding;
		do {
			
			float newX = Random.value * WIDTH;
			float newY = 0;
			float newZ = Random.value * HEIGHT;
			
			newPos = new Vector3(newX, newY, newZ);
			
			// test if the new pos is available
			
			Vector3[] testVertices = new Vector3[5];
			testVertices[0] = new Vector3(newX - bounds.extents.x, newY, newZ + bounds.extents.z);
			testVertices[1] = new Vector3(newX + bounds.extents.x, newY, newZ + bounds.extents.z);
			testVertices[2] = new Vector3(newX + bounds.extents.x, newY, newZ - bounds.extents.z);
			testVertices[3] = new Vector3(newX - bounds.extents.x, newY, newZ - bounds.extents.z);
			testVertices[4] = newPos;
			
			colliding = false;
			Vector3 origin, dest;
			for(int j = 0; j < testVertices.Length; j++) {
				dest = testVertices[j];
				origin = dest;
				origin.y += 200;
				Ray ray = new Ray(origin, dest - origin);
				RaycastHit[] hits = Physics.RaycastAll(ray);
				if(hits.Length > 0) {
					colliding = true;
					Debug.Log("COLLIDED:" + hits[0].collider.name);
					break;
				}
			}
			
		} while(colliding == true);
					
		if(disableNewGameObject) {
			newGO.SetActiveRecursively(true);
		}
		newGO.transform.position = newPos;
	}
	
	void Update() {
	}
}

1082874–40543–$InstantiateBug.zip (247 KB)

can´t you just post your code here ?
dont want to download random stuff ^^

and please put your code in code tags!

Method A)
You could do a check to see if hit results belongs to the newly instantiated object… if so ignore it but process other colliders.

Save a reference to the Instantiated Object

GameObject newGO = (GameObject)GameObject.Instantiate(cubePrefab);
Collider newObjectCollider = newGO.collider;

In your collider check code

for(int hitCount=0; hitCount < hits.Length; hitCount++)
	{
	if(hit[hitCount].collider !=newObjectCollder)
		{
		//hit on something that isn't our collider
		colliding=true;

		//need to choose a new spot for this object or try again in a different spot.
		break;
		}
	}

Method B)
You could also use layers to selectively ignore colliders, Set your prefab’s initial layer state to the “IgnoreColliders” (layer 2) layer and then move back to the normal layer (layer 0) using gameObject.layer= (layer number).

Method C)
You could also instantiate the object where it can not possibly collide with other stuff… Test spots till you find a valid (non-occupied one) and then move the object there.

Doing any of these will save you from having to toggle stuff active/inactive while testing.

Good luck.