Unity - CheckSphere 不工作?产卵仅在设备上冻结?

Unity - CheckSphere not working? spawn freezes only on device?

我试图在一个不断变化的区域(一个平面,ARKit)中生成一定数量的立方体并且不让它们重叠。我想这很简单,我在 Unity 编辑器中像这样工作:

我的问题是部署到设备 (iPhone),但一切都不一样。有几件事不起作用,我不知道为什么 - 这是一个相对简单的脚本。首先,我认为 CheckSphere 无法正常工作,规模有所不同 - 但这是我尝试获得空 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); 
                        }
                    }
                }
    }

这又一次在编辑器中完美运行。这是我设备上的代码 Im 运行(没有检查球体)

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
    }

这不会使设备崩溃,但会在同一个地方生成所有设备。我不明白为什么。如果我这样做,检查重叠:

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
    }

再次在编辑器中运行良好,但完全冻结设备。日志没有帮助,因为我每次都得到这个,即使它们没有在这些位置生成:

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

这到底是怎么回事 - 为什么它只会在这样的设备上冻结?

总结:

听起来你需要在每个重生点之间留一个短距离。

(顺便说一句,一个有用的技巧是,学习如何等到下一帧 - 查看关于它的许多文章。)


这方面的经典答案

  • 进入 "chunking" 随机算法

  • 观察方便的代码行 "How to get sets of unique random numbers."

享受


不相关的问题 -

您是否需要基本上 在生成每个立方体之间稍等片刻?

在一段时间内,它非常简单 Invoke - 您的代码模式看起来像这样:

目前...

for 1 to 100 .. spawn a cube

在每个...之间有一个暂停...

正在开始...

Call Invoke("_spawn", 1f)

然后

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

类似的示例代码 -
更简单 -

享受