【发布时间】:2016-05-15 16:02:42
【问题描述】:
我正在尝试在平面地图上随机生成块并使其不会相互重叠。 我制作了地图大小(500x500)的矩阵(c# 数组),块的比例在 1 到 5 之间。 代码有效,但如果生成的块与另一个块重叠,它会被销毁,不会在其他地方重新生成。
我尝试生成的 1000 个块中只有大约 80 个不会与另一个块重叠。
这是一张地图图片,生成了大约 80 个方块,绿色方块是方块
void generateElement(int ratio, int minScale, int maxScale, GameObject g) {
bool elementFound = false;
for (int i = 0; i < ratio * generationDefault; i++) {
GameObject el;
// Randomly generate block size and position
int size = Random.Range(minScale, maxScale + 1);
int x = Random.Range(0, mapSizex + 1 - size);
int y = Random.Range(0, mapSizey + 1 - size);
// Check if there is already an element
for (int j = x; j < x + size; j++)
for (int k = y; k < y + size; k++)
if (map[j][k] != null)
elementFound = true;
if (elementFound)
continue;
else {
el = (GameObject)Instantiate(g, new Vector3(x + (float)size / 2, (float)size / 2, y + (float)size / 2), Quaternion.Euler(0, 0, 0));
el.transform.localScale *= size;
}
// Create element on map array
for (int j = x; j < x + size; j++)
for (int k = y; k < y + size; k++)
if (map[j][k] == null) {
map[j][k] = el.GetComponent<ObjectInterface>();
}
}
}
我想到了 3 个可能的修复方法
- 我应该根据块的位置来设置块的大小。
- 我应该使用另一种随机化算法。
- 我做的不对。
你认为最好的主意是什么?
更新
我的代码工作得更好了。如果需要,我现在尝试多次实例化块(目前最多 5 个)并修复了错误。如果地图上已经有很多元素,它们不会总是被实例化,这就是我想要的,我只需要找到它尝试实例化块的正确次数。
我尝试在 500x500 的地图上实例化 1280 个元素。它只需要大约 1.5 秒,并且实例化了 1278/1280 个块 (99.843%)。
void generateElement(int ratio, int minScale, int maxScale, GameObject g) {
bool elementFound = false;
int cnt = 0;
// Generate every block
for (int i = 0; i < ratio * generationDefault; i++) {
GameObject el = null;
// Randomly generate block size and position
int size, x, y, tryCnt = 0;
// Try maximum 5 times to generate the block
do {
elementFound = false;
// Randomly set block size and position
size = Random.Range(minScale, maxScale + 1);
x = Random.Range(0, mapSizex + 1 - size);
y = Random.Range(0, mapSizey + 1 - size);
// Check if there is already an element
for (int j = x; j < x + size; j++)
for (int k = y; k < y + size; k++)
if (map[j][k] != null)
elementFound = true;
tryCnt++;
} while (elementFound && tryCnt < 5);
if (tryCnt >= 5 && elementFound) continue;
// Instantiate the block
el = (GameObject)Instantiate(g, new Vector3(x + (float)size / 2, (float)size / 2, y + (float)size / 2), Quaternion.Euler(0, 0, 0));
el.transform.localScale *= size;
// Create element on map array
for (int j = x; j < x + size; j++)
for (int k = y; k < y + size; k++)
if (map[j][k] == null) {
map[j][k] = el.GetComponent<ObjectInterface>();
}
cnt++;
}
print("Instantiated " + cnt + "/" + ratio * generationDefault);
}
【问题讨论】:
-
我能想到的一种方法(尽管它需要一些额外的数学运算),是将地图区域划分为区域网格,等于您想要放下的块数.然后,在每个区域中随机选择一个位置(考虑到块的预期比例)并在那里放置一个块。不幸的是,您还会遇到这种方法的“规律性”问题(特别是当块数相对于地图大小增加时)......不过,根据您的需要,一致的平均人口密度可能不会那么糟糕。 =P
-
嗨,Serlite。这是一种非常有名的方法。确实,这正是我在下面的答案中的内容。正如您敏锐地观察到的那样,您会根据所涉及的尺寸获得“常规外观”的结果(有时很好)。一个简单的解决方案是扰动块 - 下面给出的代码。笔记!事实上,另一种方法就是这么简单......只需将它们均匀分布(甚至不要随机化位置)然后进行扰动。只需尝试 1、2、3 或更多“扰动”,看看效果如何。
标签: c# dictionary random unity3d generator