Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Prevent Obstacles being Spawned from Overlapping

Discussion in 'Scripting' started by dyach3579, Jun 26, 2019.

  1. dyach3579

    dyach3579

    Joined:
    Jan 3, 2018
    Posts:
    22
    Hi, I haven't seen this question on Unity forums, nor have I found it by Googling it. What I'm making is a 2d Endless runner. I have my Spawner script and my Obstacle Movement script that both work great. But what I can't figure out how to do is to prevent the Obstacles from overlapping when they're spawned.

    I have the Obstacles spawning at different speeds and different positions on the Y axis, which I like that way the game isn't repetitive and boring. But one Obstacle will spawn in a certain position, then another one in the exact same position, but at a faster speed, then it overlaps the first obstacle. I would like to prevent that, but I'm not sure how. There are different Y positions where the Obstacles are being spawned from, and Im wondering if i can spawn one obstacle from that certain position, then if another obstacle spawns from that same Y position, it can only spawn when the first obstacle reaches a certain point as its moving to the left, on the X. Hopefully that makes sense.

    I am new to coding and Unity, so I appreciate any help you all are willing to give me. Thank you, and here are my Spawner and Obstacle scripts:

    Code (CSharp):
    1. public class Spawner : MonoBehaviour {
    2.  
    3.     [SerializeField] GameObject[ ] obstacles;
    4.     [SerializeField] Transform obstaclesPos;
    5.  
    6.     void Start()
    7.     {
    8.       //StartObstaclesMove();
    9.     }
    10.  
    11.     public void StartObstaclesMove()
    12.     {
    13.         StartCoroutine(InstanteObstacles(0.5f));
    14.     }
    15.  
    16.     IEnumerator InstanteObstacles ( float dt)
    17.     {
    18.         yield return new WaitForSeconds(dt);
    19.         if (GameManager.instance.bGameStarted)
    20.         {
    21.             Transform tt = obstaclesPos.GetChild(Random.Range(0, obstaclesPos.childCount));
    22.             int randomObstacle = Random.Range(0, obstacles.Length);
    23.  
    24.             GameObject obs = GameObject.Instantiate(obstacles[randomObstacle]);
    25.             obs.transform.position = tt.position;
    26.  
    27.             StartCoroutine(InstanteObstacles(dt));
    28.         }
    29.     }
    30. }

    And the Obstacle script:
    Code (CSharp):
    1. public class ObstacleMovement : MonoBehaviour {
    2.  
    3.     [SerializeField] float moveSpeed;
    4.  
    5.     public bool isEnemy = false;
    6.  
    7.     private void Awake()
    8.     {
    9.         moveSpeed = Random.Range(0.03f, 0.15f);
    10.     }
    11.  
    12.     void Update()
    13.     {
    14.         Vector3 currentpos = transform.position;
    15.         currentpos.x -= moveSpeed;  //* Time.deltaTime;
    16.         transform.position = currentpos;
    17.  
    18.         if (transform.position.y < -15f)
    19.         {
    20.             Destroy(gameObject);
    21.         }
    22.     }
    23. }
    Here's something i just tried from throwing together previous scripts, but I'm really lost. I've missed alot here:
    Code (CSharp):
    1. [SerializeField] GameObject[] obstacles;
    2. [SerializeField] Transform obstaclesPos;
    3.  
    4. [SerializeField] float minX;
    5. [SerializeField] Transform currentObstacle;
    6.  
    7.  
    8. void Start()
    9. {
    10.     //StartObstaclesMove();
    11.     while (true)
    12.     {
    13.         if (!currentObstacle || currentObstacle.position.x < minX)
    14.         {
    15.             var prefab = Random.Range(0, 10) < 5 ???;
    16.             currentObstacle = Instantiate(obstacles, Vector2(10, -4), Quaternion.identity);
    17.         }
    18.         yield;
    19.     }
    20. }
    21.  
    22. public void StartObstaclesMove()
    23. {
    24.     StartCoroutine(InstanteObstacles(2f));
    25. }
    26.  
    27. IEnumerator InstanteObstacles(float dt)
    28. {
    29.     yield return new WaitForSeconds(dt);
    30.     if (GameManager.instance.bGameStarted)
    31.     {
    32.         Transform tt = obstaclesPos.GetChild(Random.Range(0, obstaclesPos.childCount));
    33.         int randomObstacle = Random.Range(0, obstacles.Length);
    34.  
    35.         GameObject obs = GameObject.Instantiate(obstacles[randomObstacle]);
    36.         obs.transform.position = tt.position;
    37.  
    38.         StartCoroutine(InstanteObstacles(dt));
    39.     }
    40. }
    41. }
     
    Last edited: Jun 27, 2019
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,517
    Funny, we were just talking about this exact issue this morning!

    https://forum.unity.com/threads/spa...of-objects-randomly-without-collision.700679/

    But in your case you mention "different speeds" of the objects... well in that case you need to implement some kind of "oh I'm moving towards another dude, let me slow down, or tell him to speed up" type of AI.

    I'd recommend starting simple: when you move a guy, check all other guys, if you get too close to another guy, just take their motion for yourself, which would keep you the same distance, right? It might get wiggy as you have a bunch of objects all clustering, but check it out!
     
  3. axesve

    axesve

    Joined:
    Feb 4, 2019
    Posts:
    7
    What about checking collision when it's spawned?

    Code (CSharp):
    1. void OnTriggerEnter(Collider other)
    2.     {
    3.         if (other.tag == "Obstacle")
    4.         {
    5.            Destroy(this.gameObject);
    6.         }
    7.     }
     
    ksaffan190 and Kurt-Dekker like this.
  4. dyach3579

    dyach3579

    Joined:
    Jan 3, 2018
    Posts:
    22
    Hi Kurt thank you for the response. That could work, but Im not sure where Id start. I'm new to coding all this. What i was thinking is, the first obstacle spawns, and the next obstacle only spawns when the one before it reaches a certain point on the X axis. I started this code but i took it from other stuff and tried throwing it together, I'm lost
    Code (CSharp):
    1. [SerializeField] GameObject[] obstacles;
    2. [SerializeField] Transform obstaclesPos;
    3.  
    4. [SerializeField] float minX;
    5. [SerializeField] Transform currentObstacle;
    6.  
    7.  
    8. void Start()
    9. {
    10.     //StartObstaclesMove();
    11.     while (true)
    12.     {
    13.         if (!currentObstacle || currentObstacle.position.x < minX)
    14.         {
    15.             var prefab = Random.Range(0, 10) < 5 ???;
    16.             currentObstacle = Instantiate(obstacles, Vector2(10, -4), Quaternion.identity);
    17.         }
    18.         yield;
    19.     }
    20. }
    21.  
    22. public void StartObstaclesMove()
    23. {
    24.     StartCoroutine(InstanteObstacles(2f));
    25. }
    26.  
    27. IEnumerator InstanteObstacles(float dt)
    28. {
    29.     yield return new WaitForSeconds(dt);
    30.     if (GameManager.instance.bGameStarted)
    31.     {
    32.         Transform tt = obstaclesPos.GetChild(Random.Range(0, obstaclesPos.childCount));
    33.         int randomObstacle = Random.Range(0, obstacles.Length);
    34.  
    35.         GameObject obs = GameObject.Instantiate(obstacles[randomObstacle]);
    36.         obs.transform.position = tt.position;
    37.  
    38.         StartCoroutine(InstanteObstacles(dt));
    39.     }
    40. }
    41. }
     
  5. dyach3579

    dyach3579

    Joined:
    Jan 3, 2018
    Posts:
    22
    Hi Axesve, thank you for responding. I tried that, and unfortunately it didn't work. I responded with this same response to the gentleman above. What I'm wondering is if there is a way to make it so that one obstacle spawns, then the next one doesn't spawn in that same spot, until the first one reaches a certain point on the X axis. My obstacles are spawning from different points on the Y, and moving to the left on the X. Heres something i started to throw together from previous code but Im stuck. Im not at an intermediate level of coding yet unfortunately.
    Code (CSharp):
    1. [SerializeField] GameObject[] obstacles;
    2. [SerializeField] Transform obstaclesPos;
    3.  
    4. [SerializeField] float minX;
    5. [SerializeField] Transform currentObstacle;
    6.  
    7.  
    8. void Start()
    9. {
    10.     //StartObstaclesMove();
    11.     while (true)
    12.     {
    13.         if (!currentObstacle || currentObstacle.position.x < minX)
    14.         {
    15.             var prefab = Random.Range(0, 10) < 5 ???;
    16.             currentObstacle = Instantiate(obstacles, Vector2(10, -4), Quaternion.identity);
    17.         }
    18.         yield;
    19.     }
    20. }
    21.  
    22. public void StartObstaclesMove()
    23. {
    24.     StartCoroutine(InstanteObstacles(2f));
    25. }
    26.  
    27. IEnumerator InstanteObstacles(float dt)
    28. {
    29.     yield return new WaitForSeconds(dt);
    30.     if (GameManager.instance.bGameStarted)
    31.     {
    32.         Transform tt = obstaclesPos.GetChild(Random.Range(0, obstaclesPos.childCount));
    33.         int randomObstacle = Random.Range(0, obstacles.Length);
    34.  
    35.         GameObject obs = GameObject.Instantiate(obstacles[randomObstacle]);
    36.         obs.transform.position = tt.position;
    37.  
    38.         StartCoroutine(InstanteObstacles(dt));
    39.     }
    40. }
    41. }