基础房间生成
首先需要确定每次房间生成都是在上一个房间的哪个方向上生成,为此需要声明一个枚举值来记录上下左右四个方向 创建脚本RoomGenerator,声明方向枚举值
public enum Direction
{
LEFT = 0,
RIGHT = 1,
TOP = 2,
BOTTOM = 3
}
private Direction direction;
此外我们还需要声明以下几个变量
- 基础房间的GameObject变量
- 房间最大数量
- 当前已生成的所有房间列表
- 房间生成点
- X,Y轴的位置偏移量
- 起始和结束房间
public GameObject baseRoom;
public int maxCreateNum;
private List<Room> roomList = new List<Room>();
public Transform spawnPoint;
public float xOffset, yOffset;
public GameObject startRoom;
public GameObject endRoom;
转到unity,使用一个Square来暂时充当基础房间 将该sprite拖为预制体,并创建一个Room脚本,拖拽到此预制体上
设置一个房间层级Room
接下来使用随机数来确定下一次生成房间的方向
void RandomDirection()
{
direction = (Direction) Random.Range(0, 4);
switch (direction)
{
case Direction.LEFT:
spawnPoint.position += new Vector3(-xOffset, 0, 0);
break;
case Direction.RIGHT:
spawnPoint.position += new Vector3(xOffset, 0, 0);
break;
case Direction.BOTTOM:
spawnPoint.position += new Vector3(0, -yOffset, 0);
break;
case Direction.TOP:
spawnPoint.position += new Vector3(0, yOffset, 0);
break;
}
}
创建房间
void Start()
{
CreateRoom();
}
void CreateRoom()
{
for (int i = 0; i < maxCreateNum; i++)
{
CreateRoomObj(baseRoom, spawnPoint.position);
RandomDirection();
}
}
void CreateRoomObj(GameObject room, Vector3 pos)
{
GameObject obj = Instantiate(room, pos, Quaternion.identity);
roomList.Add(obj.GetComponent<Room>());
}
转到unity,新建一个Gameobject,命名为RoomGenerator,并在此对象下新建一个子对象SpawnRoomPoint 在RoomGenerator上挂载脚本RoomGenerator.cs,设置基础房间和房间生成点,X和Y轴的偏移量根据自己需要去设置 到此已经可以随机生成地图,但是生成的房间有可能会重叠
因此我们需要在移动房间生成点时进行判断,判断当前位置是否已经有一个房间
首先在BaseRoom预制体上添加一个BoxCollider2D来做占位检测 修改随机方向函数,声明一个检测半径变量
public float roomColliderRadius;
使用Physics2D.OverlapCircle函数来检测当前位置是否有房间,该方法返回一个检测到的Collider2D,如果没有则返回null
void RandomDirection()
{
do
{
direction = (Direction) Random.Range(0, 4);
switch (direction)
{
case Direction.LEFT:
spawnPoint.position += new Vector3(-xOffset, 0, 0);
break;
case Direction.RIGHT:
spawnPoint.position += new Vector3(xOffset, 0, 0);
break;
case Direction.BOTTOM:
spawnPoint.position += new Vector3(0, -yOffset, 0);
break;
case Direction.TOP:
spawnPoint.position += new Vector3(0, yOffset, 0);
break;
}
} while (Physics2D.OverlapCircle(spawnPoint.position, roomColliderRadius, roomLayer));
}
再次运行房间就不会再重叠在一起 接下来我们需要制作房间四个方向的门的判断
房间门的判断
首先我们需要声明以下几种变量
- 四个方向门的GameObject对象
- 四个bool值来判断该房间当前有哪几个方向是会出现门
- 总的门数量
public GameObject doorLeft, doorRight, doorTop, doorBottom;
public bool isLeft;
public bool isRight;
public bool isTop;
public bool isBottom;
在BaseRoom预制体下创建四个子对象,并重新命名为对应的方向枚举值,例如右边的门就是1,左边就是0 注意上面门的命名要根据方向枚举值来设置,要一一对应
public enum Direction
{
LEFT = 0,
RIGHT = 1,
TOP = 2,
BOTTOM = 3
}
在Room脚本里来初始化四个门的实例对象
void Awake()
{
foreach (Transform door in transform)
{
switch ((RoomGenerator.Direction)Convert.ToInt32(door.gameObject.name))
{
case RoomGenerator.Direction.LEFT:
doorLeft = door.gameObject;
break;
case RoomGenerator.Direction.RIGHT:
doorRight = door.gameObject;
break;
case RoomGenerator.Direction.TOP:
doorTop = door.gameObject;
break;
case RoomGenerator.Direction.BOTTOM:
doorBottom = door.gameObject;
break;
}
}
}
根据四个方向门的状态来确定需要开启哪几扇门
void Start()
{
doorLeft.SetActive(isLeft);
doorRight.SetActive(isRight);
doorBottom.SetActive(isBottom);
doorTop.SetActive(isTop);
}
更新门的总数
public void UpdateRoomState()
{
if (isLeft) doorNumber++;
if (isRight) doorNumber++;
if (isTop) doorNumber++;
if (isBottom) doorNumber++;
}
转到RoomGenerator脚本,同样使用Physics2D.OverlapCircle来判断四周是否有相邻的房间
void CheckRoomDoor(Room room, Vector3 pos)
{
Collider2D left = Physics2D.OverlapCircle(pos + new Vector3(-xOffset, 0, 0), roomColliderRadius, roomLayer);
Collider2D right = Physics2D.OverlapCircle(pos + new Vector3(xOffset, 0, 0), roomColliderRadius, roomLayer);
Collider2D top = Physics2D.OverlapCircle(pos + new Vector3(0, yOffset, 0), roomColliderRadius, roomLayer);
Collider2D bottom = Physics2D.OverlapCircle(pos + new Vector3(0, -yOffset, 0), roomColliderRadius, roomLayer);
room.isLeft = left;
room.isRight = right;
room.isTop = top;
room.isBottom = bottom;
room.UpdateRoomState();
}
在创建完房间后调用上面的方法来开启房间对应方向的门
void Start()
{
CreateRoom();
foreach (var room in roomList)
{
CheckRoomDoor(room, room.transform.position);
}
}
最终效果 目前完整脚本 RoomGenerator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoomGenerator : MonoBehaviour
{
public enum Direction
{
LEFT = 0,
RIGHT = 1,
TOP = 2,
BOTTOM = 3
}
public GameObject baseRoom;
private Direction direction;
public int maxCreateNum;
public LayerMask roomLayer;
private List<Room> roomList = new List<Room>();
public GameObject startRoom;
public GameObject endRoom;
public Transform spawnPoint;
public float xOffset, yOffset;
public float roomColliderRadius;
public Color startColor;
public Color endColor;
void Start()
{
CreateRoom();
foreach (var room in roomList)
{
CheckRoomDoor(room, room.transform.position);
}
startRoom = roomList[0].gameObject;
endRoom = roomList[maxCreateNum - 1].gameObject;
startRoom.GetComponent<SpriteRenderer>().color = startColor;
endRoom.GetComponent<SpriteRenderer>().color = endColor;
}
void Update()
{
}
void RandomDirection()
{
do
{
direction = (Direction) Random.Range(0, 4);
switch (direction)
{
case Direction.LEFT:
spawnPoint.position += new Vector3(-xOffset, 0, 0);
break;
case Direction.RIGHT:
spawnPoint.position += new Vector3(xOffset, 0, 0);
break;
case Direction.BOTTOM:
spawnPoint.position += new Vector3(0, -yOffset, 0);
break;
case Direction.TOP:
spawnPoint.position += new Vector3(0, yOffset, 0);
break;
}
} while (Physics2D.OverlapCircle(spawnPoint.position, roomColliderRadius, roomLayer));
}
void CreateRoom()
{
for (int i = 0; i < maxCreateNum; i++)
{
CreateRoomObj(baseRoom, spawnPoint.position);
RandomDirection();
}
}
void CreateRoomObj(GameObject room, Vector3 pos)
{
GameObject obj = Instantiate(room, pos, Quaternion.identity);
roomList.Add(obj.GetComponent<Room>());
}
void CheckRoomDoor(Room room, Vector3 pos)
{
Collider2D left = Physics2D.OverlapCircle(pos + new Vector3(-xOffset, 0, 0), roomColliderRadius, roomLayer);
Collider2D right = Physics2D.OverlapCircle(pos + new Vector3(xOffset, 0, 0), roomColliderRadius, roomLayer);
Collider2D top = Physics2D.OverlapCircle(pos + new Vector3(0, yOffset, 0), roomColliderRadius, roomLayer);
Collider2D bottom = Physics2D.OverlapCircle(pos + new Vector3(0, -yOffset, 0), roomColliderRadius, roomLayer);
room.isLeft = left;
room.isRight = right;
room.isTop = top;
room.isBottom = bottom;
room.UpdateRoomState();
}
void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(spawnPoint.position,roomColliderRadius);
}
}
Room.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Room : MonoBehaviour
{
public GameObject doorLeft, doorRight, doorTop, doorBottom;
public bool isLeft;
public bool isRight;
public bool isTop;
public bool isBottom;
public int doorNumber;
void Awake()
{
foreach (Transform door in transform)
{
switch ((RoomGenerator.Direction)Convert.ToInt32(door.gameObject.name))
{
case RoomGenerator.Direction.LEFT:
doorLeft = door.gameObject;
break;
case RoomGenerator.Direction.RIGHT:
doorRight = door.gameObject;
break;
case RoomGenerator.Direction.TOP:
doorTop = door.gameObject;
break;
case RoomGenerator.Direction.BOTTOM:
doorBottom = door.gameObject;
break;
}
}
}
void Start()
{
doorLeft.SetActive(isLeft);
doorRight.SetActive(isRight);
doorBottom.SetActive(isBottom);
doorTop.SetActive(isTop);
}
public void UpdateRoomState()
{
if (isLeft) doorNumber++;
if (isRight) doorNumber++;
if (isTop) doorNumber++;
if (isBottom) doorNumber++;
}
}
|