为什么Unity的Tilemap.HasSyncTileCallback()在将磁贴设置为磁贴图时造成滞后尖峰?

问题描述 投票:-1回答:1

我在我的游戏中使用Unity的二维磁贴图系统,它在旧版本的游戏中工作得非常好。在这个新版本中,当玩家移动时,我生成了20x20的块,因为世界是程序生成的。除了我设置瓷砖的时候,一切都很正常。当我这样做的时候,我在我的剖析器中得到了Tilemap.HasSyncTileCallback(),它非常昂贵,导致我的系统飙升到几帧左右,并产生一些垃圾。有什么办法可以解决这个问题吗?

我调用的函数是这样的

terrainMap.SetTile(tempVect, StaticDatabase.database.Tiles[chunk.tiles[i, j].tileIDs[0]]); terrainMap.SetTileFlags(tempVect, TileFlags.None); terrainMap.SetColor(tempVect, chunk.tiles[i, j].tileColors[0]);

我也只用SetTile函数运行了这段代码,但性能仍然不好。

我有一个想法来解决这个问题,就是在这些变化期间停止回调和刷新,然后手动调用它来停止每次调用的更新,但我甚至不知道如何访问这些参数。

目前,我使用unity的磁贴系统来制作图形和碰撞器,因为我有自己的磁贴实现,以 "MyTile "的形式。我是否应该停止使用unity的磁贴系统,而尝试其他方法,如对象池或纹理轰炸?

两个源头,一个有同样的问题https:/forum.unity.comthreadssettile-is-slow-plans-implement-ecs-pattern-to-tilemap.639619。

另一个是纹理轰炸https:/forum.unity.comthreadstile-map-accelerator-高性能基于着色器的tile-map-renderer.708413。

谢谢你的帮助!我正在使用Unity的二维贴图系统来制作我的游戏,它在旧版本的游戏中运行得非常好。

c# unity3d
1个回答
0
投票

在测试了多种不同的方法后,我找到了一个解决方案。在任何一种大循环中调用SetTile()都有高性能的代价。如果你需要放置大量的瓷砖,可以调用另一个方法,比如SetTileBlock()。这可以避免那些Tilemap.TileSyncCallbacks和refreshTile(),或者至少将它们保持在最低限度。

这是我在上面的问题中为解决这个问题所做的代码。

public void loadTerrainFromChunk(MyChunk chunk)
    {
        Tile[] terrainTiles = new Tile[chunkSize * chunkSize];
        for (int i = 0; i < chunkSize; i++)
        {
            for (int j = 0; j < chunkSize; j++)
            {
                Vector3Int tempVect = new Vector3Int(chunk.tiles[i, j].index.x, chunk.tiles[i, j].index.y, 0);
                int tempIndex = i + (j * chunkSize);
                if (chunk.tiles[i, j].tileIDs[0] != -1)
                {
                    terrainTiles[tempIndex] = ScriptableObject.CreateInstance("Tile") as Tile;
                    terrainTiles[tempIndex].sprite = StaticDatabase.database.Tiles[chunk.tiles[i, j].tileIDs[0]].sprite;
                    terrainTiles[tempIndex].name = StaticDatabase.database.Tiles[chunk.tiles[i, j].tileIDs[0]].name;
                    Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 90f * seededRandom.Next(3)), Vector3.one);
                    terrainTiles[tempIndex].transform = matrix;
                    terrainTiles[tempIndex].flags = TileFlags.None;
                    terrainTiles[tempIndex].color = chunk.tiles[i, j].tileColors[0];

                }
            }
        }

        terrainMap.SetTilesBlock(new BoundsInt(chunk.index.x*chunkSize, chunk.index.y*chunkSize, 1, chunkSize, chunkSize, 1), terrainTiles);

    }

你需要做的是

1) 创建一个数组来存放你的磁贴。

2) 创建你想要的磁贴的实例,并将它们加载到数组中。

3)(可选)修改该数组中的磁贴。

4) 将该数组加载到SetTilesBlock()函数中。

祝你有个愉快的一天

© www.soinside.com 2019 - 2024. All rights reserved.