如何提高程序世界生成性能
How to improve procedural world generation performance
我正在创建一个程序加载的 minecraft 风格的游戏。世界是由 16 个块堆叠而成的块列构建的。每个块都是一个由 16x16x16 块制成的立方体,这些块又由四边形制成(出于性能原因)。
当我的播放器四处移动时,我希望渲染特定半径内的块列。每个 tick 我检查哪些块列在玩家的半径内,然后渲染它们。发生这种情况时,世界会冻结 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;
}
}
}
}
}
深入研究您的项目代码,您似乎在每次更新时都在构建整个可见世界。也就是说,您正在为所有可见块四边形 每帧 创建新的游戏对象,然后在重新开始之前将它们全部扔掉(希望如此,否则您将发生巨大的内存泄漏)下一帧。
一种更有效的方法是在定义 world.chunksColumns.chunks 之后实例化所有游戏对象一次,然后在块 类 中使用 SetActive(true)
或 setActive(false)
'呈现调用。那么上面的代码应该 运行 快得多。
我正在创建一个程序加载的 minecraft 风格的游戏。世界是由 16 个块堆叠而成的块列构建的。每个块都是一个由 16x16x16 块制成的立方体,这些块又由四边形制成(出于性能原因)。
当我的播放器四处移动时,我希望渲染特定半径内的块列。每个 tick 我检查哪些块列在玩家的半径内,然后渲染它们。发生这种情况时,世界会冻结 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;
}
}
}
}
}
深入研究您的项目代码,您似乎在每次更新时都在构建整个可见世界。也就是说,您正在为所有可见块四边形 每帧 创建新的游戏对象,然后在重新开始之前将它们全部扔掉(希望如此,否则您将发生巨大的内存泄漏)下一帧。
一种更有效的方法是在定义 world.chunksColumns.chunks 之后实例化所有游戏对象一次,然后在块 类 中使用 SetActive(true)
或 setActive(false)
'呈现调用。那么上面的代码应该 运行 快得多。