Search Unity

Physics.OverlapSphere issue

Discussion in 'Scripting' started by Cyrussphere, Jul 2, 2020.

  1. Cyrussphere

    Cyrussphere

    Joined:
    Jul 1, 2016
    Posts:
    129
    I have a strange issue with a Physics.Overlap code that I just cant seem to figure out, was hoping someone might be able to offer suggestions. I have an GenerateGalaxy function kicked off on void Start. Its a big function but basically goes through and creates a spiral galaxy, instantiates map prefabs into Vector3 positions, and then adds the Data and the Map Object into a list. Within the same function once the above is done I then have a FindNeighbors() function that goes through the list and uses a Physics.OverlapSphere on each map object to find other nearby map objects to record back into the List Data. At the end the list has 1000 items in it and the Physics.OverlapSphere ends up just pulling all 1000 items into the neighbor data on just the 4th and 6th item in the list while everything else is empty and I am completely baffled.

    I added a Debug.Log to make sure the foreach loop is in fact going through all 1000 stars and that each one has an assigned mapobject which it does, so it doesn't seem to be an issue with Timing and the code kicking off before all the MapObjects can be Instantiated;

    Code (CSharp):
    1.  
    2. //Neighbors for map path finding
    3.   foreach (Star item in StarSystems)
    4.   {
    5.         Debug.Log("Finding Neighbor for " + item.mapObject);
    6.          FindNeighbors(item);
    7.    }
    This is the function for the FindNeighbors, if I adjust the radius to below 40 then none of the stars will get any neighbors, if I put it to 40 and above then I get just only a few stars pulling in every map object into their neighbor list.

    Code (CSharp):
    1.     void FindNeighbors(Star starData)
    2.     {
    3.         GameObject go = starData.mapObject;
    4.  
    5.         Collider[] hitColliders = Physics.OverlapSphere(go.transform.position, 40);
    6.         foreach (Collider col in hitColliders)
    7.         {
    8.             if (col.gameObject.tag == "MapSun")
    9.                 starData.neighbors.Add(col.gameObject);
    10.         }
    11.     }
    As far as the star map objects themselves, this is how they are constructed;
    MapStar - Tag "MapSun", Layer "Map", Sphere Collider attached
    - Empty GameObject as child, No Tag, Layer "MapUI", no collider
    - Two Particle System objects, no Tag, Layer "MapUI", no collider

    I also attached a screenshot of the Star List during runtime, shows the first three stars, position, and neighbor lists. Been going in circles on this for a few days so id appreciate any advice!
     

    Attached Files:

  2. Zer0Cool

    Zer0Cool

    Joined:
    Oct 24, 2014
    Posts:
    203
    Put this into a script class onto your mapObjects, so you can see the region of the FindNeighbors function:
    Code (CSharp):
    1.  void OnDrawGizmosSelected()
    2.     {
    3.         // Display the radius of the FindNeighbors function
    4.         Gizmos.color = Color.white;
    5.         Gizmos.DrawWireSphere(transform.position, 40f);
    6.     }
    If you then select all mapObjects in the scene view you should see the regions...
    I assume the distance between your Starsystems are much bigger than only 40 in radius ...

    At the end check the positions of all mapObjects because this is the base for the neighbor search and make sure all objects are already created when you do the neighbor search.
     
    Last edited: Jul 2, 2020
  3. Cyrussphere

    Cyrussphere

    Joined:
    Jul 1, 2016
    Posts:
    129
    The radius would have been my first assumption as well if not for all neighbors going into a single neighbor list, it seems there is some type of collider detection. I did the gizmo suggestion and added a screenshot of what it looks like. The map is fairly small so 60-40 range is meant to find just nearby neighbors. Your last comment made me also wonder if there was some object placement jumping around going on so I threw in a quick Debug.Log(col.gameObject.name + " " + col.transform.position); check just before the if tag check and attached that screenshot. The pos seems to match the position within the master Star List.
     

    Attached Files:

  4. Zer0Cool

    Zer0Cool

    Joined:
    Oct 24, 2014
    Posts:
    203
    So the Physics.OverlapSphere should hit all colliders in the sphere drawen by the gizmo. You should check this in the debug.log of your method:
    Code (CSharp):
    1. foreach (Collider col in hitColliders)
    2.         {
    3.           Debug.Log("Found MapSun",  col.gameObject);
    4.            if (col.gameObject.tag == "MapSun")
    5.                 starData.neighbors.Add(col.gameObject);
    6.         }
    After the debug.log click these objects in the console log to see it in scene.

    Therefore i would execute your method only for 1 system (where the neighbors are wrong / not found):

    Code (CSharp):
    1. //Neighbors for map path finding
    2. int index = 0;
    3. foreach (Star item in StarSystems)
    4.   {
    5.     index++;
    6.       if (index = 4)   {
    7.        Debug.Log("Finding Neighbor for " + item.mapObject);
    8.         FindNeighbors(item);
    9.       }
    10.    }
     
  5. Cyrussphere

    Cyrussphere

    Joined:
    Jul 1, 2016
    Posts:
    129
    Thanks for the tip, I used your idea of doing these one at a time and added in a bunch of new Debug logs but it ended up adding to the confusion. I used the same foreach loop with index but changed the FindNeighbors function to;

    Code (CSharp):
    1. void FindNeighbors(Star starData)
    2.     {
    3.         GameObject go = starData.mapObject;
    4.         Debug.Log("We got to the Find Neighbors " + go.name + " " + go.transform.position);
    5.  
    6.         Collider[] hitColliders = Physics.OverlapSphere(go.transform.position, 40);
    7.  
    8.         Debug.Log(hitColliders.Length);
    9.  
    10.         foreach (Collider col in hitColliders)
    11.         {
    12.             Debug.Log("Found MapSun", col.gameObject);
    13.             if (col.gameObject.tag == "MapSun")
    14.                 starData.neighbors.Add(col.gameObject);
    15.         }
    16.     }
    I tested this out on Index 2, it goes through but finds no colliders when doing the Physics.OverlapSphere. I then set it to Index 3 (which was getting all the stars in the list) and it indeed found all 1000 stars despite being outside of the 40 radius. I attached the screenshots of both.

    Though it would be a performance hit I may try adding the Physics.Overlap to the map object itself and try calling it from there to see what happens. This does seem to be something odd with the Physics.OverlapSphere function. Also I did have to download both Burst and Mathmatics from the Package Manager for a 3rd party graphics toolkit, but those just add some extra libraries and wouldnt imagine it would tie into this.
     

    Attached Files:

  6. Zer0Cool

    Zer0Cool

    Joined:
    Oct 24, 2014
    Posts:
    203
    So basically both 2 and 3 are wrong.
    Perhaps try this. Make a simple script and simply call the Physics.OverlapSphere only for these 2 spots in your scene:

    Produces this the same results? Attach this class anywhere and press S

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class SearchNeighbours : MonoBehaviour
    7. {
    8.  
    9.     void Update()
    10.     {
    11.         if (Input.GetKeyDown(KeyCode.S)
    12.         {
    13.             Collider[] hitColliders = Physics.OverlapSphere(new Vector3(-34f,0f,-21.1f, 40f));
    14.             Debug.Log("Pos 1: " +hitColliders.Length);
    15.             // Spawn a sphere on the position
    16.             GameObject sphere1 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    17.             sphere1.transform.position = new Vector3(-34f,0f,-21.1f, 40f);
    18.             sphere1.transform.localScale = 40f;
    19.  
    20.             Collider[] hitColliders = Physics.OverlapSphere(new Vector3(-12.6f,-3f,116.2f, 40f));
    21.             Debug.Log("Pos 2: " +hitColliders.Length);
    22.             GameObject sphere2 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    23.             sphere2.transform.position = new Vector3(-12.6f,-3f,116.2f, 40f);
    24.             sphere2.transform.localScale = 40f;
    25.  
    26.         }
    27.     }
    28.  
    29. }
    30.  
    31. /code]
     
  7. Cyrussphere

    Cyrussphere

    Joined:
    Jul 1, 2016
    Posts:
    129
    So this idea worked. I even rearranged it to create the spheres first and use that position in the Overlap. Both came back with decent numbers; Pos 1 was 52 and Pos 2 was 26. Much better then the 0 and 1000 coming off the actual map objects. Now I just need to figure out why this one worked but mine didn't.

    EDIT:
    So I guess in the end it was still just a timing issue which still baffles me since the position numbers and everything was still checking out. I moved the FIndNeighbor function into Update with a bool check to see if neighbors had generated yet and now its pulling back lists of neighbors.

    If I had any hair left to pull out it would have been gone after this but I appreciate the second set of eyes and help debugging this!
     
    Last edited: Jul 2, 2020
  8. Zer0Cool

    Zer0Cool

    Joined:
    Oct 24, 2014
    Posts:
    203
    So its presumably a timing problem of the creation time of the GO instances. So you should create all GOs first in the scene and after this loop through all creates GOs.
     
    Cyrussphere likes this.
  9. Cyrussphere

    Cyrussphere

    Joined:
    Jul 1, 2016
    Posts:
    129
    Appreciate the help through all of this. I ended up putting the galaxy generator into an IEnumerator and putting a second pause within the galaxy generation and then moving onto the finding neighbors function..seems to do the trick
     
    Zer0Cool likes this.