1

I am trying to spawn a set number of cubes within an ever changing area (a plane, ARKit) and NOT have them overlap. Pretty simple I'd think, and I have this working in Unity editor like so:

enter image description here

My problem is deploy to device (iPhone) and everything is different. Several things aren't working, and I don't know why - it's a relatively simple script. First I thought CheckSphere wasn't working, something with scale being different - but this is how I try to get an empty space:

public Vector3 CheckForEmptySpace (Bounds bounds)
    {
        float sphereRadius = tierDist;
            Vector3 startingPos = new Vector3 (UnityEngine.Random.Range(bounds.min.x, bounds.max.x), bounds.min.y, UnityEngine.Random.Range(bounds.min.z, bounds.max.z));
                // Loop, until empty adjacent space is found
                var spawnPos = startingPos; 
                while ( true )
                {
            if (!(Physics.CheckSphere(spawnPos, sphereRadius, 1 << 0)) )   // Check if area is empty
                        return spawnPos;    // Return location
                    else
                    {
                        // Not empty, so gradually move position down. If we hit the boundary edge, move and start again from the opposite edge.
                        var shiftAmount = 0.5f;
                        spawnPos.z -= shiftAmount;

                    if ( spawnPos.z < bounds.min.z )
                        {
                            spawnPos.z = bounds.max.z;
                            spawnPos.x += shiftAmount;

                    if ( spawnPos.x > bounds.max.x )
                        spawnPos.x = bounds.min.x;

                        }
                        // If we reach back to a close radius of the starting point, then we didn't find any empty spots
                        var proximity = (spawnPos - startingPos).sqrMagnitude;
                        var range = shiftAmount-0.1;    // Slight 0.1 buffer so it ignores our initial proximity to the start point
                        if ( proximity < range*range )  // Square the range
                        {
                            Debug.Log( "An empty location could not be found" );
                            return new Vector3 (200, 200, 200); 
                        }
                    }
                }
    }

This again, works perfect in editor. This is the code Im running on my device (without check sphere)

public void spawnAllTiers(int maxNum)
    {

        if(GameController.trackingReady && !hasTriedSpawn)
        {
            hasTriedSpawn = true;

            int numTimesTried = 0;
            BoxCollider bounds = GetGrid ();
            if (bounds != null) {

                while (tiersSpawned.Length < maxNum && numTimesTried < 70) { //still has space
                    Tier t = getNextTier ();

                    Vector3 newPos = new Vector3 (UnityEngine.Random.Range(GetGrid ().bounds.min.x, GetGrid ().bounds.max.x), GetGrid ().bounds.min.y, UnityEngine.Random.Range(GetGrid ().bounds.min.z, GetGrid ().bounds.max.z));

                    //Vector3 newPos = CheckForEmptySpace (bounds.bounds);

                    if(GetGrid ().bounds.Contains(newPos)) //meaning not 200 so it is there
                    {
                        spawnTier (newPos, t);
                    }

                    numTimesTried++;
                    platformsSpawned = GameObject.FindObjectsOfType<Platform> ();
                    tiersSpawned = GameObject.FindObjectsOfType<Tier> ();
                }

                if(tiersSpawned.Length < maxNum)
                {
                    print ("DIDNT REACH - maxed at "+tiersSpawned.Length);
                }

            }
        }

        //maybe check for num times trying, or if size of all spawned tiers is greater than area approx
    }

    //SPAWN NEXT TIER
    public void spawnTier(Vector3 position, Tier t) //if run out of plats THEN we spawn up like tree house
    {

        print ("SUCCESS - spawn "+position+"SPHERE: "+Physics.CheckSphere(position, tierDist, 1 << 0));
//      Vector3 pos = currentTier.transform.position; //LATER UNCOMMENT - would be the current tier spawning from


        //TO TEST comment to this line ---------------------------------------------------------------------------
        #if UNITY_EDITOR 

        Instantiate (t, position, Quaternion.identity);
        anchorManager.AddAnchor(t.gameObject);

        #else 

        //------------------------------------------------------------------------------------------
        Instantiate (t, position, Quaternion.identity);
        anchorManager.AddAnchor(t.gameObject);

        #endif
    }

This doesnt crash the device but spawns ALL in the same place. I cant understand why. If I do this, CHECKING for overlap:

public void spawnAllTiers(int maxNum)
    {

        if(GameController.trackingReady && !hasTriedSpawn)
        {
            hasTriedSpawn = true;

            int numTimesTried = 0;
            BoxCollider bounds = GetGrid ();
            if (bounds != null) {

                while (tiersSpawned.Length < maxNum && numTimesTried < 70) { //still has space
                    Tier t = getNextTier ();

                    //Vector3 newPos = new Vector3 (UnityEngine.Random.Range(GetGrid ().bounds.min.x, GetGrid ().bounds.max.x), GetGrid ().bounds.min.y, UnityEngine.Random.Range(GetGrid ().bounds.min.z, GetGrid ().bounds.max.z));

                    Vector3 newPos = CheckForEmptySpace (GetGrid ().bounds);

                    if(GetGrid ().bounds.Contains(newPos) && t) //meaning not 200 so it is there
                    {
                        spawnTier (newPos, t);
                    }

                    numTimesTried++;
                    platformsSpawned = GameObject.FindObjectsOfType<Platform> ();
                    tiersSpawned = GameObject.FindObjectsOfType<Tier> ();
                }

                if(tiersSpawned.Length < maxNum)
                {
                    print ("DIDNT REACH - maxed at "+tiersSpawned.Length);
                }

            }
        }

        //maybe check for num times trying, or if size of all spawned tiers is greater than area approx
    }

Works great in editor again, but completely freezes the device. Logs are not helpful, as I just get this every time, even though they aren't spawning in those positions:

SUCCESS - spawn (0.2, -0.9, -0.9)SPHERE: False
SUCCESS - spawn (-0.4, -0.9, 0.2)SPHERE: False
SUCCESS - spawn (0.8, -0.9, 0.2)SPHERE: False
SUCCESS - spawn (-0.4, -0.9, -0.8)SPHERE: False
SUCCESS - spawn (0.9, -0.9, -0.8)SPHERE: False

What the hell is happening - why would it freeze only on device like this?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
blue
  • 7,175
  • 16
  • 81
  • 179
  • **note** add some very simple statements "Debug.Log .." to discover what is going on. Often something is looping much more than you think. put in more and more Debug.Log statements, until you see the issue! – Fattie Apr 16 '18 at 20:43

1 Answers1

1

Summary:

it sounds like you needed a short gap between each spawn.

(BTW a useful trick is, learn how to wait until the next frame - check out many articles on it.)


All-time classic answer for this

https://stackoverflow.com/a/35228592/294884

  • get in to "chunking" for random algorthims

  • observe the handy line of code at "How to get sets of unique random numbers."

Enjoy


Unrelated issue -

Could it be you need to basically wait a small moment between spawning each cube?

For a time in unity it's very simply Invoke - your code pattern would look something like this:

Currently ...

for 1 to 100 .. spawn a cube

To have a pause between each ...

In Start ...

Call Invoke("_spawn", 1f)

and then

func _spawn() {
   if count > 70 .. break
   spawn a cube
   Invoke("_spawn", 1f)
}

Similar example code - https://stackoverflow.com/a/36736807/294884
Even simpler - https://stackoverflow.com/a/35807346/294884

Enjoy

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • Alrighty.. thank you. Thing is, before implementing im thinking the iPhone will still balk due to some memory thing.. is there a way to make the existing code work if im only spawning max 20 cubes? also all cubes are same size – blue Apr 16 '18 at 20:28
  • indeed it needed a wait time.. My only issue now is check sphere isn't really working - they all spawn on top of each other. Is this a known issue with ARKit in the real world space/iphone in general? – blue Apr 17 '18 at 21:17
  • 1
    glad we solved the problem @skyguy . Regarding "all in the same spot - AR issue", really you'd have to ask a new question on that one. – Fattie Apr 17 '18 at 21:21