Endless Runner "Treadmill" 与对象池的差距

Gaps in Endless Runner "Treadmill" with Object Pooling

我正在开发一款 3D 无尽跑酷游戏,其中玩家静止不动,background/obstacles 在他们周围移动。我正在使用对象池。

背景由大型 "City Block" 对象的多个变体组成,其中包含地面的 3D 平面立方体对象。每个 City Block 对象在街道上都有不同种类的障碍物,但这些对象是父对象 "CityBlock" 的子对象,因此会随之移动。这些城市街区在屏幕外彼此重叠,并且有两个是默认的起始街区,排成一行并放置在屏幕中。激活后,它们有一个脚本,可以简单地沿 x 轴移动它们。当他们越过玩家到达某个点时,他们会重置回到屏幕外的起始位置。

我创建了一个游戏对象列表,并在编辑器中用场景中的城市街区填充它。然后将列表随机化,"activates" 索引为 0 的那个,然后递增并继续激活下一个。

每次到达列表末尾时,我都会重新随机化,然后再次循环。这样,游戏应该是真正随机的,而不是每次迭代都在相同的对象循环中循环。

我的问题是我经常在背景 "treadmill" 中以 "gaps" 结束,它构成了整个城市街区的大小,这是我能够解决这个问题的唯一方法问题是使用递归,如果它到达已经激活的城市街区,则再次调用该方法。这会在目标移动设备上造成性能问题,并不能完全解决问题(经过几次迭代后,差距再次出现)。

我觉得我在某个兔子洞里走得太远了,或者我的视野太狭窄了,必须有更好的方法来随机化游戏对象列表并随机激活它们。

public class CityBlockManager : MonoBehaviour {

public List<GameObject> cityBlockList = new List<GameObject>(); //List is populated in-editor, not through script

public int listSize;

public int counter; //Only made public to be seen in editor


//Use this for initialization
//On initialization, will determine the size of the list, randomize it, and active the first member of that list.
void Start () {

    listSize = cityBlockList.Count - 1;

    RandomizeList();

    cityBlockList[0].GetComponent<CityBlockMover>().isActive = true;

}

//Given the list of any size of game objects, will randomize/shuffle it
void RandomizeList()
{
    for (int i = 0; i <= listSize; i++)
    {
        GameObject temp = cityBlockList[i];
        int randomIndex = Random.Range(i, cityBlockList.Count);
        cityBlockList[i] = cityBlockList[randomIndex];
        cityBlockList[randomIndex] = temp;
    }

}

//Keeps track of how many members of the list have been activated, and if it reaches the full list, will randomize the list over again.
//On each call, will activate the next game object in the list.

public void ActivateNext()
{
    counter++;

    if (counter > listSize || cityBlockList[counter] == null)
    {
        counter = 0;
        RandomizeList(); //Re-randomize list, start over


        //Helps ensure there are no gaps in city block "spawning"
        if(cityBlockList[0].GetComponent<CityBlockMover>().isActive != true)
        {
            cityBlockList[0].GetComponent<CityBlockMover>().isActive = true;
            return;
        }
        else
        {
            ActivateNext();
            return;
        }

    }

    if (cityBlockList[counter].GetComponent<CityBlockMover>().isActive == false && cityBlockList[counter] != null)
    {
        cityBlockList[counter].GetComponent<CityBlockMover>().isActive = true;

    }
    else
    {
        counter++;
        if (counter > listSize || !cityBlockList[counter])
        {
            counter = 0;
            RandomizeList();
            if (cityBlockList[0].GetComponent<CityBlockMover>().isActive != true)
            {
                cityBlockList[0].GetComponent<CityBlockMover>().isActive = true;
            }
            else
            {
                ActivateNext();
                return;
            }
        }
    }
}
}

考虑使用 2 个列表,一个活动块列表和一个非活动块列表,这样问题可能会变得更清楚。

另外,如果你只使用一个列表,RandomizeList(); 在它只包含几个非活动块时会变得非常低效,它会在第一个随机给你一个非活动块之前被频繁调用地点 - 这也是使用 2 个列表的原因。

通过确保在项目设置 > 脚本执行顺序中的默认时间之前调用移动我的环境的脚本,我能够解决我的无限运行器项目发生的问题。

这是因为我跟踪道路位置并实例化新道路的脚本是运行 我的移动环境脚本之前。当 Unity 实际执行 实例化时导致位置过时。