Are there any ways to check collision?

I create an object and wanna check collision this new object with others. cause i don’t want to place trees too close to each other. So there is a code from one script.

private IEnumerator GenerateTrees()
    {
        //yield return new WaitForSecondsRealtime(2f);
        for (int i = 0; i < amountTrees; i++)
        {
            var border = sizeX - delta;
            var pos = new Vector3(Random.Range(-border, border), 0, Random.Range(-border, border));
            var tree = GenerateObject(treesPrefabs);
            SetRandomPosition(tree, border);
            yield return new WaitForEndOfFrame();
            //yield return new WaitForSecondsRealtime(2f);
            while (tree.GetComponent<CollisionDetector>().hasCollision)
            {
                print("while");
                SetRandomPosition(tree, border);
                yield return new WaitForEndOfFrame();
                //yield return new WaitForSecondsRealtime(2f);
            }
        }
    }

And there is from other which is attached for every prefab.

public class CollisionDetector : MonoBehaviour
{
    public bool hasCollision;

    private void OnTriggerEnter(Collider collision)
    {
        if (collision.gameObject.layer == 6)
        {
            hasCollision = true;
        }
    }

    private void OnTriggerExit(Collider collision)
    {
        if (collision.gameObject.layer == 6)
        {
            hasCollision = false;
        }
    }
}

It seems that code in the second can’t update in time. That’s why the first script doesn’t generate new position for tree. But when coroutine is done, i can see in inspector that hasCollision is true. Maybe there is a way to wait for end of the seconds cript update?

2 Answers

2

Few ways/alternatives I can think of

  1. Use [PhysicsScene][1] / [PhysicsScene2D][2]
  2. Place trees at grid coordinates where the width/height of a cell are the minimum distance radius

`void PlaceTrees(int maxCount, int maxIterations) {
bool[,] used = new bool[width, height];
int count = 0;

  for (int i = 0; i < maxIterations && count < maxCount; ++i)
  {
     int x = RandomValue();
     int y = RandomValue();

    // place tree
  
    if (!used[x,y]) {
      used[x,y] = true;
      ++count;
    }
  }
}`
  1. Bite the bullet and implement some collision checking yourself. If you aren’t placing that many trees you could just nest two for loops
    bool CanPlaceTree(Vector3 candidatePosition, List trees) { for (int i = 0; i < trees.Length; ++i) { Vector3 delta = candidatePosition - trees*;* *if (delta.sqrMag < minSqrDistance)* *{* *return false;* *}* *}* *return true;* *}*
    You could look up an implementation of a [QuadTree][3] to help
    [1]: Unity - Scripting API: PhysicsScene
    [2]: Unity - Scripting API: PhysicsScene2D
    [3]: GitHub - splitice/QuadTrees: High Performance Quad Tree Implementations for C# (Point, Rect and PointInv)

You want to yield return WaitForFixedUpdate() to wait for the collision checking to happen. If your problem is that you don’t want the tree to appear and then teleport once the collision checking happens, you could maybe just make it invisible by disabling the renderer by default and activate it when a valid position has been verified.