Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Instantiating without overlapping prefabs

Discussion in 'Scripting' started by idrog, Oct 14, 2016.

  1. idrog

    idrog

    Joined:
    Jul 30, 2016
    Posts:
    83
    hello all! I am making an endless runner and have one more question. When I am instantiating my prefabs for my endless runner a lot of them are overlapping. How would I go about fixing this? The prefabs are coming out fine, I just cant figure out how to make them not overlap. Would someone know how to go about doing this? I plan on using an array to use a few more prefabs in the long run if that would change someones answer to this question. Thanks!

    for (int i = 0; i < 5; i++)
    {
    Vector2 position = new Vector2(Random.Range(-2f, 2f), Random.Range(-2f, 4f));
    Instantiate(Largeb, position, Quaternion.identity);
    }
     
  2. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    In Physics class, Unity has overlap methods as OverlapSphere or OverlapBox to detect other actors in that position.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Test : MonoBehaviour {
    5.  
    6.     public GameObject prefab;
    7.     public int numberOfActors = 15;  
    8.  
    9.     void Update () {
    10.  
    11.         while (GameObject.FindGameObjectsWithTag(this.prefab.tag).Length < this.numberOfActors)
    12.         {
    13.  
    14.             Vector3 position;
    15.            
    16.             do
    17.             {
    18.                
    19.                 position = new Vector3(Random.Range(-10f, 10f), 0.5f, Random.Range(-10f, 10f));
    20.  
    21.             } while (Physics.OverlapSphere(position, 1f).Length > 0);
    22.  
    23.             (Instantiate(prefab) as GameObject).transform.position = position;
    24.            
    25.         }
    26.    
    27.     }
    28. }
    Use these overlap methods to prevent overlaping.
     
    xehanotN0 and idrog like this.
  3. Kalladystine

    Kalladystine

    Joined:
    Jan 12, 2015
    Posts:
    227
    @IsGreen - the idea I agree with, but not the implementation. It was just an example, sure, but since it's public someone will use it and get burned badly.

    This is a high potential infinite loop and could backfire very quickly - what if there isn't a valid place to spawn at this particular frame? There needs to be at least an exit condition in the while close.
    Time to find a spawn point can also vary wildly (depending on how dense the scene should be).

    A more complete (and safe) example would be to use the Overlap* functions to loop through possible positions, add them them to a collection and choose one randomly.

    Example:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. public class RunnerSpawnTest : MonoBehaviour
    5. {
    6.     public GameObject PrefabToSpawn;
    7.     public int MaxNumberOfActors = 15;
    8.     public float MinX = -2f;
    9.     public float MaxX = 2f;
    10.     public float MinY = -2f;
    11.     public float MaxY = 4f;
    12.  
    13.     [Range(min: 0.1f, max: 1f)] // clamp Step to some reasonable values
    14.     public float Step = 1f;
    15.  
    16.     private int activeActorCount;
    17.     private List<Vector2> spawnablePositions;
    18.  
    19.     void Start()
    20.     {
    21.         activeActorCount = 0;
    22.         spawnablePositions = new List<Vector2>();
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         // untested
    28.         // preferably move all this to a separate method and call only under some condition
    29.         // f.e. time based
    30.         // missing: actors should -- activeActorCount when they're destroyed
    31.  
    32.         if (activeActorCount >= MaxNumberOfActors)
    33.         {
    34.             return;
    35.         }
    36.  
    37.         for (float x = MinX; x < MaxX; x += Step)
    38.         {
    39.             for (float y = MinY; x < MaxY; y += Step)
    40.             {
    41.                 if (Physics.OverlapSphere(new Vector2(x, y), Step).Length == 0)
    42.                 {
    43.                     spawnablePositions.Add(new Vector2(x, y));
    44.                 }
    45.             }
    46.         }
    47.  
    48.         if (spawnablePositions.Count == 0)
    49.         {
    50.             return; // nowhere to spawn
    51.         }
    52.  
    53.         for (int i = activeActorCount; i <= MaxNumberOfActors; i++)
    54.         {
    55.             int randomPosition = Random.Range(0, spawnablePositions.Count);
    56.             GameObject.Instantiate(PrefabToSpawn, spawnablePositions[randomPosition], Quaternion.identity);
    57. spawnablePositions.RemoveAt(randomPosition);
    58.         }
    59.  
    60.         spawnablePositions.Clear();
    61.     }
    62. }
     
    Last edited: Oct 15, 2016
    idrog and Simpso like this.
  4. idrog

    idrog

    Joined:
    Jul 30, 2016
    Posts:
    83
    Thanks a lot for your help bud. It really helped me out a lot! Again, I know I keep saying it but I appreciate your persistent help because you have commented on many of my posts! :)

     
  5. idrog

    idrog

    Joined:
    Jul 30, 2016
    Posts:
    83
    Thanks for your help kally! IT really helped in understanding what I was trying to do. Sorry for the late thank you, I usually thank people the first 10 minutes of their help but this has been a hectic week. I really am appreciating your and the whole unity community in helping me to understand my problems! :)

     
  6. jterry

    jterry

    Joined:
    Oct 30, 2014
    Posts:
    9
    Speaking of infinite loops, in the 2nd for loop, you check if x < MaxY, I believe you mean if y < MaxY.