二维程序世界生成的动态多维数组
Dynamic Multi-Dimensional array for 2D Procedural World Gen
目标
我正在构建一个世界生成器,它应该能够在相机接近已存在的边缘时将 "voxels" 动态添加到某种列表中。每个体素都应该尽可能高效地访问,因为每帧都需要访问数千个列表中的几百个体素。
我考虑过的方法
1) 我的第一个想法是体素的多维数组,它的索引是体素的 x 和 y 坐标:
Voxels[,] voxels = new Voxel[128,128];
优点:假设我知道体素的坐标,这应该非常快:Voxel myVoxel = voxels[x, y];
缺点:我要么必须限制世界大小,要么每次我想生成新地形时都必须完全重新创建数组...
2) 为了解决这个问题,我想我可以将 x 和 y 值存储在一个字符串中,并将它们用作字典中的键。 Dictionary<string, Voxel> voxels = new Dictionary<string, Voxel>();
Voxel myVoxel = voxels[x + "," + y];
然后添加到列表中就像调用 .Add(); 一样简单。方法。
问题
1) 从数组中提取数据的效率与从字典中提取数据有何不同。在我看来,数组会快很多,因为我假设字典必须遍历每个键来检查相等性(如果我错了请原谅我的无知)
2) 如果一个数组真的是 那 从中拉出的速度要快得多,将破坏并重新创建一个包含数百个以上的数组每秒多次处理数千项(取决于块大小)值得吗?
请注意,目标平台是手机,并非生成的每个体素都会存储在 ram 中,因此列表永远不会变得非常大。仍然需要进行测试以确定具体尺寸,但概念是存在的...
提前致谢
对于您的问题,
1) 如果知道元素在数组中的索引,数组最快(O(1)时间) .例如,如果您使用的是世界位置,则可以使用每个体素的世界位置坐标的底部作为它们在 3D 数组中的索引。基本上,当您从 3D 数组生成世界时,使用索引作为世界位置,然后您将能够使用 Math.floor(worldPosition)[=34 在恒定时间内找到它们的索引=] 在你的 3D 阵列中 - 这是最快的。
当您在不知道索引的情况下搜索未排序的数据结构时,字典比数组快。看图here(未排序列表的字典查找是O(1),数组查找是O(n))。
2) 您可能需要使用多线程才能运行。例如,您可以使用不同的线程为 3D 数组的每个四分之一生成数据,然后将这些线程与主线程连接起来以生成对象。你不应该 运行 遇到这种方法的问题,只要你在将线程加入主线程后生成对象并且只使用其他线程生成 3D 数组(如果你是使用 Unity,则不能在其他线程中使用任何 Unity 库函数。
此外,如果您使用的是 Unity,我强烈建议您查看 Sebastian Lague 关于地形生成的视频以获得其他最佳实践 https://www.youtube.com/watch?v=wbpMiKiSKm8&list=PLFt_AvWsXl0eBW2EiBtl_sxmDtSgZBxB3
目标
我正在构建一个世界生成器,它应该能够在相机接近已存在的边缘时将 "voxels" 动态添加到某种列表中。每个体素都应该尽可能高效地访问,因为每帧都需要访问数千个列表中的几百个体素。
我考虑过的方法
1) 我的第一个想法是体素的多维数组,它的索引是体素的 x 和 y 坐标:
Voxels[,] voxels = new Voxel[128,128];
优点:假设我知道体素的坐标,这应该非常快:Voxel myVoxel = voxels[x, y];
缺点:我要么必须限制世界大小,要么每次我想生成新地形时都必须完全重新创建数组...
2) 为了解决这个问题,我想我可以将 x 和 y 值存储在一个字符串中,并将它们用作字典中的键。 Dictionary<string, Voxel> voxels = new Dictionary<string, Voxel>();
Voxel myVoxel = voxels[x + "," + y];
然后添加到列表中就像调用 .Add(); 一样简单。方法。
问题
1) 从数组中提取数据的效率与从字典中提取数据有何不同。在我看来,数组会快很多,因为我假设字典必须遍历每个键来检查相等性(如果我错了请原谅我的无知)
2) 如果一个数组真的是 那 从中拉出的速度要快得多,将破坏并重新创建一个包含数百个以上的数组每秒多次处理数千项(取决于块大小)值得吗?
请注意,目标平台是手机,并非生成的每个体素都会存储在 ram 中,因此列表永远不会变得非常大。仍然需要进行测试以确定具体尺寸,但概念是存在的...
提前致谢
对于您的问题,
1) 如果知道元素在数组中的索引,数组最快(O(1)时间) .例如,如果您使用的是世界位置,则可以使用每个体素的世界位置坐标的底部作为它们在 3D 数组中的索引。基本上,当您从 3D 数组生成世界时,使用索引作为世界位置,然后您将能够使用 Math.floor(worldPosition)[=34 在恒定时间内找到它们的索引=] 在你的 3D 阵列中 - 这是最快的。
当您在不知道索引的情况下搜索未排序的数据结构时,字典比数组快。看图here(未排序列表的字典查找是O(1),数组查找是O(n))。
2) 您可能需要使用多线程才能运行。例如,您可以使用不同的线程为 3D 数组的每个四分之一生成数据,然后将这些线程与主线程连接起来以生成对象。你不应该 运行 遇到这种方法的问题,只要你在将线程加入主线程后生成对象并且只使用其他线程生成 3D 数组(如果你是使用 Unity,则不能在其他线程中使用任何 Unity 库函数。
此外,如果您使用的是 Unity,我强烈建议您查看 Sebastian Lague 关于地形生成的视频以获得其他最佳实践 https://www.youtube.com/watch?v=wbpMiKiSKm8&list=PLFt_AvWsXl0eBW2EiBtl_sxmDtSgZBxB3