带有对象池的无尽跑步者“跑步机”中的空隙

时间:2018-07-25 15:51:56

标签: c# unity3d recursion object-pooling

我正在研究一种3D无尽的跑步游戏,其中玩家静止不动,背景/障碍物在它们周围移动。我正在使用对象池。

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

我创建了一个GameObjects列表,并在编辑器中填充了场景中的City Blocks。然后将该列表随机化,并在索引0处“激活”一个列表,然后递增并继续激活下一个列表。

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

我的问题是,我经常在后台“跑步机”中出现“空白”,这构成了整个城市街区的大小,而我能够解决此问题的唯一方法是使用递归,即如果到达已激活的城市街区,则再次使用该方法。这会在目标移动设备上造成性能问题,并且不能完全解决问题(经过多次迭代后,差距再次出现)。

我觉得我离某个兔子洞太远了,或者对此感到不知所措,因此必须有一种更好的方法来随机分配游戏对象列表并随机激活它们。

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 个答案:

答案 0 :(得分:0)

考虑使用2个列表,一个活动块列表和一个非活动块列表,也许问题会以这种方式变得更加清楚。

此外,如果仅使用1个列表,则RandomizeList();仅包含几个非活动块时会变得非常低效,因此在它首先随机给您一个非活动块之前,它会经常被调用-这也是使用2个列表的原因。

答案 1 :(得分:0)

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

这是因为跟踪环境位置并实例化新道路的脚本正在运行。当Unity 实际上执行实例化时,结果会过时。