所以我目前正在创建一个带有程序世界生成的游戏。因此,我经常加载和卸载大量的世界数据。过程如下:
第 1 步:加载块后,它会获得一个线程工作线程,该线程工作线程在单独的线程中从文件中读取数据。 该工作人员还准备“原型对象”,其中包含稍后实例化我的游戏对象所需的大部分数据。这包括诸如用于设置纹理的 Color 数组和用于设置碰撞器的 Vector2 数组之类的内容。
第 2 步:线程完成后,会将完成的原型对象放入 ConcurrentQueue 中,并在主线程中将其出队并用于初始化游戏对象。这包括添加脚本和 SpriteRenderer 作为组件,以及将 createUninitialized 标志设置为 true 来初始化 Texture2D。
第 3 步:创建碰撞器以及将 Color 数组应用于纹理以及随后的 Apply() 调用将在稍后处理(效果很好,但超出了本文的范围)
如您所见,这种情况或多或少有规律地发生。我首先怀疑垃圾收集器清除与它有关,因为你可以看到它与这里的这个尖峰对齐。但其他人的情况似乎并非如此...... 此外,它似乎与纹理大小无关,因为在此处突出显示的两种情况下,纹理的大小均为 160x160,大多数情况下都是这种情况...
无论如何,这是在突出显示的“创建对象”部分中进行分析的代码:
public static PhixelObject Create(Chunk chunk, Vector3Int chunkPos, List<Vector2> verticies, List<Phixel> perimeterPhixels, Phixel[,] phixelMatrix, GameObject gameObject = null)
{
//Create create
PhixelObject phixelObject = Create<PhixelObject>(gameObject);
//this just creates a new GameObject and adds the script as a component
//Set Transform
phixelObject.transform.localScale = new Vector3(Constants.PIXEL_PER_METER, Constants.PIXEL_PER_METER, 1);
phixelObject.transform.parent = chunk.transform;
phixelObject.transform.localPosition = new Vector3(chunkPos.x - Constants.CHUNK_SIZE / 2, chunkPos.y - Constants.CHUNK_SIZE / 2, -chunkPos.z);
//Add Sprite Renderer
phixelObject.textureRenderer = phixelObject.AddComponent<SpriteRenderer>();
//"create Texture_x" + phixelObject.dims.x.ToString() + "_y"+ phixelObject.dims.y.ToString()
phixelObject.tex = new Texture2D(phixelObject.dims.x, phixelObject.dims.y, TextureFormat.RGBA32, -1, false, true);
return phixelObject;
}
(为了可读性,我用注释替换了手动 Profile.BeginSample() 调用,并删除了未分析的部分)
总的来说,我觉得很奇怪,例如相同的Texture2D初始化连续20次需要0.05毫秒,然后一次或两次需要40毫秒,然后又回到0.05毫秒。
如上所述,纹理大小不能不同,因为它们在大多数情况下都是相同的。 我也没有完全排除 GC 问题,但我已将类更改为结构,将引用类型数组更改为值类型数组,以便更轻松地收集内容。
所以我希望有人知道这里发生了什么, 或者至少可以给我一些找到罪魁祸首的提示。 预先感谢您的任何帮助! :)
编辑:
所以我现在已经有了一个运行流畅的版本,但需要采取很多步骤才能到达那里。
问题的根源似乎是太多、太大的texture.apply()调用、仍然超载的垃圾收集器以及过去几个月增长的大量意大利面条代码的组合。
答案更复杂,我更详细地介绍了这里 但是 tl;博士: