代码之家  ›  专栏  ›  技术社区  ›  blue

Unity-CheckSphere不工作?繁殖仅在设备上冻结?

  •  1
  • blue  · 技术社区  · 6 年前

    我试图在一个不断变化的区域(一个平面,ARKit)内生成一定数量的立方体,并且不让它们重叠。我认为这很简单,我在Unity editor中的工作如下:

    enter image description here

    我的问题是部署到设备(iPhone),一切都不一样。有几件事不起作用,我不知道为什么——这是一个相对简单的脚本。首先,我认为CheckSphere不起作用,比例有所不同,但这就是我尝试获取空白空间的方式:

    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); 
                            }
                        }
                    }
        }
    

    这同样适用于编辑器。这是我在设备上运行的代码(不带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
        }
    

    这不会使设备崩溃,但会在同一个地方产生。我不明白为什么。如果执行此操作,请检查重叠:

    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
    

    到底发生了什么-为什么它只会在这样的设备上冻结?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Fattie    6 年前

    总结:

    听起来你需要在每一次繁殖之间留一小段间隔。

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


    经典答案

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

    • 进入随机算法的“分块”

    • 观察“How to get set 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)
    }
    

    类似示例代码- https://stackoverflow.com/a/36736807/294884
    更简单- https://stackoverflow.com/a/35807346/294884

    享受