-почти доделал базовую генерацию

This commit is contained in:
vladislove 2026-10-02 20:39:19 +03:00
parent 6f0520f9a0
commit 47f59350c8
4 changed files with 182 additions and 60 deletions

View File

@ -13840,11 +13840,9 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 2197e0e0f0e04dbaa19b690f03f10300, type: 3} m_Script: {fileID: 11500000, guid: 2197e0e0f0e04dbaa19b690f03f10300, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: Assembly-CSharp::_Project.Scripts.LevelGenerating.WallsGenerator m_EditorClassIdentifier: Assembly-CSharp::_Project.Scripts.LevelGenerating.WallsGenerator
roomCountMin: 0
roomCountMax: 0
floorsCount: 10 floorsCount: 10
lengthWallMin: 0 lengthWallMin: 5
lengthWallMax: 0 lengthWallMax: 25
lengthStartRoom: 10 lengthStartRoom: 10
lengthFloor: 100 lengthFloor: 100
corridorLength: 5 corridorLength: 5

View File

@ -21,5 +21,10 @@ namespace _Project.Scripts.LevelGenerating
// return Rooms[Rooms.Count - 1]; // return Rooms[Rooms.Count - 1];
return Rooms.Last(); return Rooms.Last();
} }
public List<Room> GetRooms()
{
return Rooms;
}
} }
} }

View File

@ -5,10 +5,10 @@ namespace _Project.Scripts.LevelGenerating
{ {
public class Room public class Room
{ {
public Room(Vector2 position, int wigth, int length, RoomType rt):this() public Room(Vector2 position, int width, int length, RoomType rt):this()
{ {
Position = position; Position = position;
Wigth = wigth; Width = width;
Length = length; Length = length;
this.rt = rt; this.rt = rt;
} }
@ -18,27 +18,27 @@ namespace _Project.Scripts.LevelGenerating
exits = new List<ExitsInRoomType>(); exits = new List<ExitsInRoomType>();
} }
public Room(Vector2 position, int wigth, int length, RoomType rt, EntranceToRoomType entrance):this() public Room(Vector2 position, int width, int length, RoomType rt, EntranceToRoomType entrance):this()
{ {
Position = position; Position = position;
Wigth = wigth; Width = width;
Length = length; Length = length;
this.rt = rt; this.rt = rt;
this.entrance = entrance; this.entrance = entrance;
} }
public Room(int wigth, int length, RoomType rt):this() public Room(int width, int length, RoomType rt):this()
{ {
Wigth = wigth; Width = width;
Length = length; Length = length;
this.rt = rt; this.rt = rt;
} }
public Room(Vector2 position, int wigth, int length, RoomType rt, bool isWallable, EntranceToRoomType entrance, List<ExitsInRoomType> exits) public Room(Vector2 position, int width, int length, RoomType rt, bool isWallable, EntranceToRoomType entrance, List<ExitsInRoomType> exits)
{ {
Position = position; Position = position;
Wigth = wigth; Width = width;
Length = length; Length = length;
this.rt = rt; this.rt = rt;
this.entrance = entrance; this.entrance = entrance;
@ -46,8 +46,8 @@ namespace _Project.Scripts.LevelGenerating
this.exits = exits; this.exits = exits;
} }
public int Wigth { get; set; } public int Width { get; set; }//width - по оси z
public int Length { get; set; } public int Length { get; set; }//length- по оси x
public Vector2 Position; public Vector2 Position;
public RoomType rt { get; set; } public RoomType rt { get; set; }
public EntranceToRoomType entrance { get; set; } public EntranceToRoomType entrance { get; set; }

View File

@ -1,13 +1,15 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.Design.Serialization; using System.ComponentModel.Design.Serialization;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using Random = UnityEngine.Random;
namespace _Project.Scripts.LevelGenerating namespace _Project.Scripts.LevelGenerating
{ {
public class WallsGenerator : MonoBehaviour public class WallsGenerator : MonoBehaviour
{ {
[SerializeField] private int roomCountMin;
[SerializeField] private int roomCountMax;
[SerializeField] private int floorsCount; [SerializeField] private int floorsCount;
[SerializeField] private int lengthWallMin; [SerializeField] private int lengthWallMin;
[SerializeField] private int lengthWallMax; [SerializeField] private int lengthWallMax;
@ -24,15 +26,34 @@ namespace _Project.Scripts.LevelGenerating
void Start() void Start()
{ {
levelManager = LevelManager.Instance; levelManager = LevelManager.Instance;
CreateStartRoom(); GenerateFloor();
} }
void GenerateRooms() void GenerateFloor()
{ {
RoomCount = Random.Range(roomCountMin, roomCountMax); CreateStartRoom();
LevelManager.Rooms.Add(new Room(Vector2.zero,lengthStartRoom, lengthStartRoom,RoomType.Start)); Instantiate(GameObjectA, new Vector3(0,-1,0), Quaternion.identity);
foreach (var room in levelManager.GetRooms())
{
float x = room.Position.x;
float z = room.Position.y; // В Vector2 ось Y отвечает за Z в 3D пространстве Unity
float length = room.Length;
float width = room.Width;
// 4 угла комнаты:
// 1. Нижний левый (X, Z)
Instantiate(GameObjectB, new Vector3(x, 0, z), Quaternion.identity);
// 2. Нижний правый (X + Length, Z)
Instantiate(GameObjectB, new Vector3(x + length, 0, z), Quaternion.identity);
// 3. Верхний правый (X + Length, Z + Width)
Instantiate(GameObjectB, new Vector3(x + length, 0, z + width), Quaternion.identity);
// 4. Верхний левый (X, Z + Width)
Instantiate(GameObjectB, new Vector3(x, 0, z + width), Quaternion.identity);
}
} }
Room CreateCorridor(Vector2 posRoom, int Length, int Wigth, ExitsInRoomType exitType) Room CreateCorridor(Vector2 posRoom, int Length, int Wigth, ExitsInRoomType exitType)
{ {
Vector2 corridorPos = Vector2.zero; Vector2 corridorPos = Vector2.zero;
@ -109,11 +130,11 @@ namespace _Project.Scripts.LevelGenerating
LevelManager.Rooms.Add(corridor); LevelManager.Rooms.Add(corridor);
// Визуализация коридора (расставляем маркеры по углам коридора для наглядности) // // Визуализация коридора (расставляем маркеры по углам коридора для наглядности)
Instantiate(GameObjectB, new Vector3(corridorPos.x, 0, corridorPos.y), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(corridorPos.x, 0, corridorPos.y), Quaternion.identity);
Instantiate(GameObjectB, new Vector3(corridorPos.x + cLength, 0, corridorPos.y), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(corridorPos.x + cLength, 0, corridorPos.y), Quaternion.identity);
Instantiate(GameObjectB, new Vector3(corridorPos.x + cLength, 0, corridorPos.y + cWidth), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(corridorPos.x + cLength, 0, corridorPos.y + cWidth), Quaternion.identity);
Instantiate(GameObjectB, new Vector3(corridorPos.x, 0, corridorPos.y + cWidth), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(corridorPos.x, 0, corridorPos.y + cWidth), Quaternion.identity);
return corridor; return corridor;
} }
@ -121,46 +142,143 @@ namespace _Project.Scripts.LevelGenerating
{ {
if (prevRoom == null || prevRoom.exits.Count == 0) return; if (prevRoom == null || prevRoom.exits.Count == 0) return;
// if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2),
// exitForCor))
// {
// Room newRoom = GenerateRandomRoom();
// newRoom.Position = new Vector2();
// newRoom.rt = RoomType.Undefined;
// newRoom.entrance = EntranceToRoomType.XAxisP;
// newRoom.exits = new List<ExitsInRoomType>();
// if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2),
// newRoom.Length, newRoom.Width, exitForCor))
// {
// newRoom.isWallable = false;
// levelManager.AddRoom(newRoom);
// CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
// }
// else
// {
// newRoom.isWallable = true;
// EditRoomFoFitting(newRoom);
// levelManager.AddRoom(newRoom);
// CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
// }
// }
Room newRoom = GenerateRandomRoom();
newRoom.rt = RoomType.Undefined;
newRoom.exits = new List<ExitsInRoomType>();
Vector2 newRoomPos = Vector2.zero;
// Вычисляем позицию новой комнаты и откуда в нее входит коридор
switch (exitForCor) switch (exitForCor)
{ {
// Если вышли направо, новая комната слева получает вход (-X)
case ExitsInRoomType.XAxisP: case ExitsInRoomType.XAxisP:
{ newRoom.entrance = EntranceToRoomType.XAxisN;
if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2), newRoomPos = new Vector2(
exitForCor)) prevRoom.Position.x + prevRoom.Length + corridorLength, // Сдвигаем на ширину пред. комнаты и коридор
{ prevRoom.Position.y + (prevRoom.Width / 2f) - (newRoom.Width / 2f) // Центрируем по оси Y (Z)
Room newRoom = GenerateRandomRoom(); );
newRoom.Position = new Vector2(); break;
newRoom.rt = RoomType.Undefined;
newRoom.entrance = EntranceToRoomType.XAxisP; // Если вышли налево
newRoom.exits = new List<ExitsInRoomType>(); case ExitsInRoomType.XAxisN:
if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2), newRoom.entrance = EntranceToRoomType.XAxisP;
newRoom.Length, newRoom.Wigth, exitForCor)) newRoomPos = new Vector2(
{ prevRoom.Position.x - corridorLength - newRoom.Length, // Отступаем влево на коридор и ширину новой комнаты
newRoom.isWallable = false; prevRoom.Position.y + (prevRoom.Width / 2f) - (newRoom.Width / 2f)
levelManager.AddRoom(newRoom); );
CreateCorridor(newRoom.Position,newRoom.Length,newRoom.Wigth,exitForCor); break;
}
else // Если вышли вверх (+Z/Y)
{ case ExitsInRoomType.ZAxisP:
newRoom.isWallable = true; newRoom.entrance = EntranceToRoomType.ZAxisN;
EditRoomFoFitting(newRoom,exitForCor); newRoomPos = new Vector2(
levelManager.AddRoom(newRoom); prevRoom.Position.x + (prevRoom.Length / 2f) - (newRoom.Length / 2f), // Центрируем по оси X
} prevRoom.Position.y + prevRoom.Width + corridorLength
} );
break;
// Если вышли вниз (-Z/Y)
case ExitsInRoomType.ZAxisN:
newRoom.entrance = EntranceToRoomType.ZAxisP;
newRoomPos = new Vector2(
prevRoom.Position.x + (prevRoom.Length / 2f) - (newRoom.Length / 2f),
prevRoom.Position.y - corridorLength - newRoom.Width
);
break; break;
}
} }
// Устанавливаем просчитанную позицию
newRoom.Position = newRoomPos;
// Проверяем, помещается ли комната с ее реальными размерами
if (IsRoomCanFit(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor))
{
newRoom.isWallable = false;
levelManager.AddRoom(newRoom);
CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
}
else
{
newRoom.isWallable = true;
EditRoomFoFitting(newRoom); // Подгоняем размеры под границы карты
// Проверяем, вмещается ли хотя бы комната минимального размера после обрезки
if (newRoom.Length >= lengthWallMin && newRoom.Width >= lengthWallMin)
{
levelManager.AddRoom(newRoom);
CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
}
else
{
// Места не хватило даже для минимальной комнаты.
// Отменяем создание этой комнаты и завершаем ветку.
// При необходимости здесь можно удалить сгенерированный к ней коридор.
return;
}
}
if (exitForCor != ExitsInRoomType.XAxisN) TryPlaceRoom(newRoom, ExitsInRoomType.XAxisP);
// 2. Влево (-X): идем, только если TryPlaceRoomНЕ слеа (XAxisP)
if (exitForCor != ExitsInRoomType.XAxisP) TryPlaceRoom(newRoom, ExitsInRoomType.XAxisN);
// 3. Вверх/Вперед (+Z): идем, только TryPlaceRoomпришли НЕ верху (ZAxisN)
if (exitForCor != ExitsInRoomType.ZAxisN) TryPlaceRoom(newRoom, ExitsInRoomType.ZAxisP);
// 4. Вниз/Назад (-Z): идем, только если TryPlaceRoomишли НЕ сниу (ZAxisP)
if (exitForCor != ExitsInRoomType.ZAxisP) TryPlaceRoom(newRoom, ExitsInRoomType.ZAxisN);
} }
private void EditRoomFoFitting(Room room) private void EditRoomFoFitting(Room room)
{ {
if (room.Position.x + room.Length - lengthFloor <= 0) if (lengthFloor - room.Position.x + room.Length <= 0)
{ {
room.Length = lengthFloor - Convert.ToInt32(room.Position.x);
} }
if (lengthFloor - room.Position.y + room.Width <= 0)
{
room.Width = lengthFloor - Convert.ToInt32(room.Position.y);
}
if (room.Position.x < 0)
{
room.Position.x = 0;
}
if (room.Position.y < 0)
{
room.Position.y = 0;
}
} }
@ -276,7 +394,7 @@ namespace _Project.Scripts.LevelGenerating
int b = Random.Range(lengthWallMin, lengthWallMax); int b = Random.Range(lengthWallMin, lengthWallMax);
Room room = new Room(); Room room = new Room();
room.Length = a; room.Length = a;
room.Wigth = b; room.Width = b;
return room; return room;
} }
@ -346,15 +464,16 @@ namespace _Project.Scripts.LevelGenerating
room.entrance = EntranceToRoomType.Null; room.entrance = EntranceToRoomType.Null;
LevelManager.Rooms.Add(room); LevelManager.Rooms.Add(room);
Instantiate(GameObjectA, new Vector3(0,-1,0), Quaternion.identity); // Instantiate(GameObjectA, new Vector3(0,-1,0), Quaternion.identity);
//
Instantiate(GameObjectB, new Vector3(xR,0,zR), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(xR,0,zR), Quaternion.identity);
Instantiate(GameObjectB, new Vector3(xR+lengthStartRoom,0,zR), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(xR+lengthStartRoom,0,zR), Quaternion.identity);
Instantiate(GameObjectB, new Vector3(xR+lengthStartRoom,0,zR+lengthStartRoom), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(xR+lengthStartRoom,0,zR+lengthStartRoom), Quaternion.identity);
Instantiate(GameObjectB, new Vector3(xR,0,zR+lengthStartRoom), Quaternion.identity); // Instantiate(GameObjectB, new Vector3(xR,0,zR+lengthStartRoom), Quaternion.identity);
CreateCorridor(new Vector2Int(xR, zR),lengthStartRoom,lengthStartRoom,room.exits.First()); CreateCorridor(new Vector2Int(xR, zR),lengthStartRoom,lengthStartRoom,room.exits.First());
Room firstCorridor = CreateCorridor(new Vector2(xR, zR), lengthStartRoom, lengthStartRoom, room.exits.First()); Room firstCorridor = CreateCorridor(new Vector2(xR, zR), lengthStartRoom,
lengthStartRoom, room.exits.First());
if (firstCorridor != null) if (firstCorridor != null)
{ {
TryPlaceRoom(room,room.exits.First()); TryPlaceRoom(room,room.exits.First());