我正在做一个3D无止境的跑步游戏,玩家是静止的,背景/障碍在他们周围移动。我正在使用对象池。
背景由一个大型“城市街区”物体的多个变体组成,该物体由一个地面三维平面立方体物体组成。每个城市街区对象在街道上都有不同种类的障碍物,但是这些对象是父"CityBlock“的子对象,因此可以使用它移动。这些城市街区在屏幕上互相覆盖,并且有两个是默认的起始区,排列起来放在屏幕上。当激活时,他们有一个脚本,只需沿x轴移动.当他们到达超过玩家的某个点时,他们会在屏幕外重新回到他们的起始位置。
我创建了一个GameObjects列表,并在编辑器中使用场景中的City块填充它。然后将列表随机化,“激活”索引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;
}
}
}
}
}发布于 2018-08-23 07:19:26
考虑使用两个列表,一个活动块列表和一个非活动块列表,这样问题可能会变得更清楚。
另外,如果您只使用一个列表,那么当RandomizeList();只包含几个非活动块时,它就会变得非常低效,在它一开始随机地给出一个非活动块之前,它将经常被调用--这也是使用两个列表的原因。
发布于 2020-01-02 05:04:53
当这个问题发生在我的无限运行程序项目时,我能够解决这个问题,方法是确保在项目设置>脚本执行顺序中的默认时间之前调用移动我的环境的脚本。
这是因为跟踪道路位置和实例化新道路的脚本在移动环境脚本之前运行。当Unity实际执行实例化时,会导致一个陈旧的位置。
https://stackoverflow.com/questions/51523117
复制相似问题