我正在创建按程序加载的《我的世界》风格的游戏。世界是由大块列构成的,大块列是16个大块的堆栈。每个块都是由16x16x16块组成的多维数据集,而这些块又由四边形组成(出于性能原因)。
[我的播放器四处移动时,我希望呈现特定半径内的块列。我每次打勾时都会检查哪些块列在播放器的半径内,然后进行渲染。发生这种情况时,世界将冻结1-2秒。我已对此进行了更改,因此每个刻度仅呈现一个块,而不是整个块列。每次游戏冻结约0.5-1秒。
进行渲染的代码在这里:
// Update is called once per frame
void Update()
{
StartCoroutine("Render");
}
IEnumerator Render()
{
int radius = 2;
Vector3 currentPosition = Camera.main.transform.position;
Vector2 currentChunkPosition = new Vector2((float) Math.Floor(currentPosition.x / Chunk.size), (float) Math.Floor(currentPosition.z / Chunk.size));
float chunkColumnDistance;
for (int x = 0; x < world.Size.x; x++)
{
for (int y = 0; y < world.Size.y; y++)
{
chunkColumnDistance = Mathf.Sqrt((float) Math.Pow(x - currentChunkPosition.x, 2) + (float)Math.Pow(y - currentChunkPosition.y, 2));
if (chunkColumnDistance <= radius)
{
for (int i = ChunkColumn.chunksPerColumn - 1; i > -1; --i)
{
if (world.chunkColumns[x, y].chunks[i].rendered)
{
continue;
}
world.chunkColumns[x, y].chunks[i].Render();
yield return null;
}
}
}
}
}
我总是希望每次更新都会有一个小的延迟,但是不会到玩家可以察觉的程度。我目前正在将渲染更新作为协程运行,但是我不确定从这里开始。谁能提出建议。
供参考,项目在这里:https://github.com/JoshPJackson/BlockGame/blob/master/Assets/Scripts/Game.cs
编辑:
我进行了更改,以便仅渲染位于播放器特定半径内的块,而不渲染位于播放器半径内的块列中的每个块。性能更好,但仍然不尽如人意。
更新的代码是:
IEnumerator Render()
{
int radius = 2;
Vector3 currentPosition = Camera.main.transform.position;
float chunkDistance;
for (int x = 0; x < world.Size.x; x++)
{
for (int y = 0; y < world.Size.y; y++)
{
for (int i = ChunkColumn.chunksPerColumn - 1; i > -1; --i)
{
chunkDistance = Vector3.Distance(currentPosition, world.chunkColumns[x, y].chunks[i].globalPosition);
if (chunkDistance <= radius * Chunk.size)
{
if (world.chunkColumns[x, y].chunks[i].rendered)
{
continue;
}
world.chunkColumns[x, y].chunks[i].Render();
yield return null;
}
}
}
}
}
深入研究您的项目代码,看起来您每次更新都在构建整个可见的世界。也就是说,您要为所有可见的块四边形每个帧创建新的GameObject,然后将它们全部扔掉(希望这样,否则会造成巨大的内存泄漏),然后再重新开始下一帧。
一种更有效的方法是在定义world.chunksColumns.chunks之后实例化所有GameObject一次,然后在Block类的渲染调用中使用SetActive(true)
或setActive(false)
。然后,上面的代码应运行得更快。