Hi everyone, I am making a tool for Unity to scatter some prefabs.
In order to check if a prefab will overlap with another, I am doing the following thing.
Take the BoxCollider (set as trigger) size and center of the prefab and check if at the wished location another objects is present.
To do so, I am using the Physics.OverlapBoxNonAlloc, here is the code:
public class Scatter : MonoBehaviour {
[SerializeField] GameObject prefab;
[SerializeField] LayerMask layerMask;
[SerializeField] Grid grid;
BoxCollider boxCollider;
[ContextMenu("Scatter Prefabs")]
public void ScatterPrefab()
{
ResetScatter();
boxCollider = prefab.GetComponent<BoxCollider>();
Vector2 space = new Vector2(grid.size.x / (grid.num.x - 1), grid.size.y / (grid.num.y - 1));
GameObject go;
float posY, posX;
int count = 0;
Collider[] bufferColliders = new Collider[2];
for (int y = 0; y < grid.num.y; y++)
{
posY = y * space.y - grid.size.y / 2;
for (int x = 0; x < grid.num.x; x++)
{
posX = x * space.x - grid.size.x / 2;
Vector3 pos = new Vector3(posX, 0, posY);
int num = Physics.OverlapBoxNonAlloc(pos + boxCollider.center, boxCollider.size / 2, bufferColliders, Quaternion.identity, layerMask);
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.SetParent(transform);
cube.name = "CheckBox " + count;
cube.transform.localPosition = pos + boxCollider.center;
cube.transform.localScale = boxCollider.size;
DestroyImmediate(cube.GetComponent<BoxCollider>());
Debug.DrawRay(cube.transform.position, Vector3.up * 0.2f, Color.red, 10);
foreach (var col in bufferColliders)
{
Debug.Log(cube.name + " collides with: " + col);
}
if (num == 0)
{
go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
go.name += " " + count;
go.transform.SetParent(transform);
go.transform.localPosition = pos;
DestroyImmediate(cube);
}
count++;
}
}
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireCube(transform.position, grid.size3);
}
[ContextMenu("Reset Scatter")]
public void ResetScatter()
{
for (int i = transform.childCount - 1; i >= 0; i--)
DestroyImmediate(transform.GetChild(i).gameObject);
}
[System.Serializable]
class Grid {
public Vector2 size = Vector2.one;
public Vector2Int num = Vector2Int.one;
#region Getter & Setter
public Vector3 size3 => new Vector3(size.x, 0, size.y);
#endregion
}
}
Where a checking is done, I have instanciate a cube to see if it is the right box checking but here is the result:
The prefab is correcly instanciate, but the following are completly wrong, no prefab has been instantiate since the OverlapBox says that it collides with the first one whereas there are not event touching it.
As tou can see with the above picture, with a larger scale, it is a real mess, many prefabs are overlapping with others.