C# 如何提高程序世界生成性能

C# 如何提高程序世界生成性能,c#,performance,unity3d,procedural-generation,C#,Performance,Unity3d,Procedural Generation,我正在创建一个程序加载的minecraft风格的游戏。世界是由区块列构建的,区块列是由16个区块组成的堆栈。每个块都是由16x16x16块组成的立方体,而这些块又由四边形组成(出于性能原因) 当我的播放器四处移动时,我希望渲染特定半径内的块列。每次勾选时,我都会检查哪些区块列在播放器的半径范围内,然后渲染它们。当这种情况发生时,世界冻结了1-2秒。我改变了这一点,所以每个勾号只渲染一个块,而不是整个块列。游戏每次冻结0.5-1秒左右 执行渲染的代码如下所示: // Update is calle

我正在创建一个程序加载的minecraft风格的游戏。世界是由区块列构建的,区块列是由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;
               }
           }
        }
    }
}
//每帧调用一次更新
无效更新()
{
开始程序(“呈现”);
}
IEnumerator Render()
{
int半径=2;
Vector3 currentPosition=Camera.main.transform.position;
Vector2 currentChunkPosition=新的Vector2((float)数学地板(currentPosition.x/Chunk.size),(float)数学地板(currentPosition.z/Chunk.size));
浮动距离;
对于(intx=0;x
我总是希望每次更新都会有一点延迟,但不会到玩家可以注意到的程度。我目前正在以协同程序的形式运行渲染更新,但我不确定从这里可以走到哪里。有人能提出改进建议吗

供参考的项目如下:

// 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;
               }
           }
        }
    }
}
编辑:

我做了一个更改,这样我只渲染在玩家一定半径范围内的块,而不是chunk列中在玩家半径范围内的每个块。性能更好,但仍不尽如人意

更新后的代码为:

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;
                    }
                }
            }
        }
    }
IEnumerator Render()
{
int半径=2;
Vector3 currentPosition=Camera.main.transform.position;
浮动距离;
对于(intx=0;x-1;--i)
{
chunkDistance=Vector3.Distance(currentPosition,world.chunkColumns[x,y].chunks[i].globalPosition);

如果(chunkDistance深入到你的项目代码中,每次更新看起来你都在构建整个可见世界。也就是说,你在每一帧为所有可见块四边形创建新的游戏对象,然后在下一帧重新开始之前将它们全部扔掉(希望,否则你会有巨大的内存泄漏)


一种更有效的方法是在定义world.chunksColumns.chunks之后,实例化所有游戏对象一次,然后使用
SetActive(true)
SetActive(false)
在你的块类的渲染调用中。那么上面的代码应该运行得更快。

通常计算平方根是一个缓慢的操作,最好避免在经常运行的代码中使用,你需要快速。不完全熟悉unity中的渲染消隐,但这通常看起来是一种低效的方法。您好@rebusB。在什么情况下是低效的ent?(我对这类事情还不熟悉)我没有检查
Mathf.Sqrt(…),而是将它改为
Vector3.distance(…)
。虽然您正在迭代世界上所有的区块,但不确定这会有多大的差异,因此世界的大小将决定渲染的速度。可以从x=position.x-radius到x=position.x+radius进行迭代开始。y也是如此。这可能会节省一些宝贵的时间。谢谢@reusb。我会尝试这将在以后进行,并将接受它作为答案,如果helps@joshuajackson太棒了!谢谢…你的速度有多快?我一直在学习UnrealEngine,但从Unity开始。好吧@rebusB我在这之后不久就遇到了一个路障。你上面的想法在有少量块的时候让世界加载得非常快。但是现在我增加了块数游戏内存不足,除非我将一些块序列化为文本文件,然后在需要时加载。加载和保存会降低性能,所以我现在尝试解决这个问题:/世界有多大?如果Unity支持,你可能想看看几何体实例。我想技术上是无限的,但我正在尝试加载一个ra围绕玩家的3块dius