Сперва (как мне показалось) все работало, но происходит вот что - генератор выбирает несколько определенных шаблонов (для куска кода, представленного ниже это 2 шаблона, один из них, к слову, невозможен по условиям генерации) и начинает гонять по ним по кругу (!), совершенно не предпринимая попыток придумать новые шаблоны. Время от времени (по неустановленной закономерности) он решает при запуске сцены/игры заново сгенерировать сперва одну комнату, потом другую, третью, а потом вновь возвращается к предопределенным шаблонам.
Более того, эта последовательность шаблонов сохраняется и при перезапуске сцены. Я перезапускал также Юнити, это помогло на первые 5-6 генераций, потом он снова взялся за свое.
Судя по наблюдениям, шаблоны он выбирает исходя, в частности, из максимальной длины комнаты (она вообще выбирается СЛУЧАЙНО от 4 до 8, но если поставить от 4 до 9, например, то шаблоны будут иные), а также из стартовой клетки, из которой начинается генерация.
Для понимания идеи генерации: он берет клетку, выбирает длину комнаты влево (для комнаты, смотрящей вверх), потом длину вправо, а затем начинает двигаться вверх, пока не упрется в непустую клетку или у него не закончится его максимальная длина. Как только он заканчивает это, то приступает к окаймлению комнаты стенами, в которых изредка делает дырки, которые служат новыми коридорами/дверями, от которых потом будет происходить генерация последующих комнат.
Синтаксис:
Используется csharp
[System.Serializable]
public class GenerationMapTile
{
public int x, y;
// 0 - empty space
// 1 - wall
// 2 - floor
public int floorType = 0;
public int roomNumber;
public bool isJoint;
public bool isJointDenied;
// 1 - up
// 2 - right
// 3 - down
// 4 - left
public int jointDirection;
public bool frontSideIsConnected, rearSideIsConnected;
}
public class MapGenerator : MonoBehaviour
{
public int maxAttemptsCount;
public GenerationMapTile[,] tiles;
public List<GenerationMapTile> unfinishedJoints;
public int maxMapSizeX = 200,
maxMapSizeY = 200;
public GenerationMapTile currentJoint;
public int currentRoomNumber = 0;
public Tilemap tilemap;
public TileBase floorTile, wallTile;
private void Start()
{
tiles = new GenerationMapTile[maxMapSizeX, maxMapSizeY];
for (int x = 0; x < maxMapSizeX; x++)
for (int y = 0; y < maxMapSizeY; y++)
{
tiles[x, y] = new GenerationMapTile
{
x = x,
y = y,
floorType = 0,
isJoint = false,
roomNumber = -1
};
}
tiles[50, 50].isJoint = true;
tiles[50, 50].jointDirection = 1;
tiles[50, 50].floorType = 2;
currentJoint = tiles[50, 50];
RoomGenerationWave();
for (int x = 0; x < maxMapSizeX; x++)
for (int y = 0; y < maxMapSizeY; y++)
{
if (tiles[x, y].floorType == 1)
tilemap.SetTile(new Vector3Int(x, y, 0), wallTile);
if (tiles[x, y].floorType == 2)
tilemap.SetTile(new Vector3Int(x, y, 0), floorTile);
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
public void RoomGenerationWave()
{
if (currentJoint.isJointDenied == false)
{
currentRoomNumber++;
int jointsCount = 1;
int maxJointCounts = Random.Range(1, 5);
if (currentJoint.jointDirection == 1)
{
bool impossibleToContinue = false;
int maxRoomLength = Random.Range(4, 8);
int shiftToLeft = Random.Range(0, 7);
int shiftToRight = Random.Range(7 - shiftToLeft - 2, 7 - shiftToLeft);
if (shiftToRight < 0) shiftToRight = 0;
int y = 1;
for (int i = 0; i < maxRoomLength; i++)
{
for (int x = -shiftToLeft; x <= shiftToRight; x++)
{
if (tiles[currentJoint.x + x, currentJoint.y + y].floorType != 0)
{
impossibleToContinue = true;
break;
}
}
if (impossibleToContinue == true) break;
else
{
for (int x = -shiftToLeft; x <= shiftToRight; x++)
{
tiles[currentJoint.x + x, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + x, currentJoint.y + y].roomNumber = currentRoomNumber;
}
y++;
}
}
int maxY = y;
for (y = 0; y <= maxY; y++)
{
if (y == maxY)
{
for (int x = -shiftToLeft - 1; x <= shiftToRight; x++)
{
if (tiles[currentJoint.x + x, currentJoint.y + y].isJoint == false)
{
if (x != -shiftToLeft - 1 && x != shiftToRight + 1 && Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x + x, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + x, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x + x, currentJoint.y + y].jointDirection = 1;
tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x + x, currentJoint.y + y + 1].floorType == 2)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x + x, currentJoint.y + y]);
}
else tiles[currentJoint.x + x, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
}
}
else if (y == 0)
{
for (int x = -shiftToLeft - 1; x <= shiftToRight; x++)
{
if (tiles[currentJoint.x + x, currentJoint.y + y].isJoint == false)
{
if (x != -shiftToLeft - 1 && x != shiftToRight + 1 && Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x + x, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + x, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x + x, currentJoint.y + y].jointDirection = 1;
tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x + x, currentJoint.y + y + 1].floorType == 2)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x + x, currentJoint.y + y]);
}
else tiles[currentJoint.x + x, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
}
}
else
{
if (tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].isJoint == false)
{
if (Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].jointDirection = 4;
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x - shiftToLeft - 2, currentJoint.y + y].floorType == 2)
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y]);
}
else tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
if (tiles[currentJoint.x + shiftToRight, currentJoint.y + y].isJoint == false)
{
if (Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].jointDirection = 2;
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x + shiftToRight + 1, currentJoint.y + y].floorType == 2)
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x + shiftToRight + 1, currentJoint.y + y]);
}
else tiles[currentJoint.x + shiftToRight, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x + shiftToRight, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x + shiftToRight, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
}
}
}
}
}
}
public class GenerationMapTile
{
public int x, y;
// 0 - empty space
// 1 - wall
// 2 - floor
public int floorType = 0;
public int roomNumber;
public bool isJoint;
public bool isJointDenied;
// 1 - up
// 2 - right
// 3 - down
// 4 - left
public int jointDirection;
public bool frontSideIsConnected, rearSideIsConnected;
}
public class MapGenerator : MonoBehaviour
{
public int maxAttemptsCount;
public GenerationMapTile[,] tiles;
public List<GenerationMapTile> unfinishedJoints;
public int maxMapSizeX = 200,
maxMapSizeY = 200;
public GenerationMapTile currentJoint;
public int currentRoomNumber = 0;
public Tilemap tilemap;
public TileBase floorTile, wallTile;
private void Start()
{
tiles = new GenerationMapTile[maxMapSizeX, maxMapSizeY];
for (int x = 0; x < maxMapSizeX; x++)
for (int y = 0; y < maxMapSizeY; y++)
{
tiles[x, y] = new GenerationMapTile
{
x = x,
y = y,
floorType = 0,
isJoint = false,
roomNumber = -1
};
}
tiles[50, 50].isJoint = true;
tiles[50, 50].jointDirection = 1;
tiles[50, 50].floorType = 2;
currentJoint = tiles[50, 50];
RoomGenerationWave();
for (int x = 0; x < maxMapSizeX; x++)
for (int y = 0; y < maxMapSizeY; y++)
{
if (tiles[x, y].floorType == 1)
tilemap.SetTile(new Vector3Int(x, y, 0), wallTile);
if (tiles[x, y].floorType == 2)
tilemap.SetTile(new Vector3Int(x, y, 0), floorTile);
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
public void RoomGenerationWave()
{
if (currentJoint.isJointDenied == false)
{
currentRoomNumber++;
int jointsCount = 1;
int maxJointCounts = Random.Range(1, 5);
if (currentJoint.jointDirection == 1)
{
bool impossibleToContinue = false;
int maxRoomLength = Random.Range(4, 8);
int shiftToLeft = Random.Range(0, 7);
int shiftToRight = Random.Range(7 - shiftToLeft - 2, 7 - shiftToLeft);
if (shiftToRight < 0) shiftToRight = 0;
int y = 1;
for (int i = 0; i < maxRoomLength; i++)
{
for (int x = -shiftToLeft; x <= shiftToRight; x++)
{
if (tiles[currentJoint.x + x, currentJoint.y + y].floorType != 0)
{
impossibleToContinue = true;
break;
}
}
if (impossibleToContinue == true) break;
else
{
for (int x = -shiftToLeft; x <= shiftToRight; x++)
{
tiles[currentJoint.x + x, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + x, currentJoint.y + y].roomNumber = currentRoomNumber;
}
y++;
}
}
int maxY = y;
for (y = 0; y <= maxY; y++)
{
if (y == maxY)
{
for (int x = -shiftToLeft - 1; x <= shiftToRight; x++)
{
if (tiles[currentJoint.x + x, currentJoint.y + y].isJoint == false)
{
if (x != -shiftToLeft - 1 && x != shiftToRight + 1 && Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x + x, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + x, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x + x, currentJoint.y + y].jointDirection = 1;
tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x + x, currentJoint.y + y + 1].floorType == 2)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x + x, currentJoint.y + y]);
}
else tiles[currentJoint.x + x, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
}
}
else if (y == 0)
{
for (int x = -shiftToLeft - 1; x <= shiftToRight; x++)
{
if (tiles[currentJoint.x + x, currentJoint.y + y].isJoint == false)
{
if (x != -shiftToLeft - 1 && x != shiftToRight + 1 && Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x + x, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + x, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x + x, currentJoint.y + y].jointDirection = 1;
tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x + x, currentJoint.y + y + 1].floorType == 2)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x + x, currentJoint.y + y]);
}
else tiles[currentJoint.x + x, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x + x, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x + x, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
}
}
else
{
if (tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].isJoint == false)
{
if (Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].jointDirection = 4;
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x - shiftToLeft - 2, currentJoint.y + y].floorType == 2)
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y]);
}
else tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x - shiftToLeft - 1, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
if (tiles[currentJoint.x + shiftToRight, currentJoint.y + y].isJoint == false)
{
if (Random.Range(0f, 100f) < 15f)
{
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].floorType = 2;
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].isJoint = true;
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].jointDirection = 2;
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].rearSideIsConnected = true;
if (tiles[currentJoint.x + shiftToRight + 1, currentJoint.y + y].floorType == 2)
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].frontSideIsConnected = true;
else unfinishedJoints.Add(tiles[currentJoint.x + shiftToRight + 1, currentJoint.y + y]);
}
else tiles[currentJoint.x + shiftToRight, currentJoint.y + y].floorType = 1;
}
else
{
if (tiles[currentJoint.x + shiftToRight, currentJoint.y + y].frontSideIsConnected == false)
tiles[currentJoint.x + shiftToRight, currentJoint.y + y].frontSideIsConnected = true;
else tiles[currentJoint.x + shiftToRight, currentJoint.y + y].rearSideIsConnected = true;
jointsCount++;
}
}
}
}
}
}
}
Буду благодарен за помощь или хотя бы за подсказку.