Spawn the next room by opening a door.
Hello there,
what i have: a set of 4 identical rooms, each with four doors. the only difference is the room's contetnt. Lets call them A, B, C, D.
what i want to do: starting for example in room A, opening a random door, the room behind this door have to be random. B, C or D. Let it be room B for our example. After entering room B the door is closed (atomatical) and room A is deleted. Now we are in room B and by opening a random door the next to be spawned may be A, C or D. And so on.
My qestion is how this kind of script spawning the rooms is called. Or where i have to look after support.
I repeat once again, all the rooms are already created by me. The only thing to do is to randomly spawn them at the right place at the right time.
Looking forward to your answers.
Answer by Quertie · May 31, 2016 at 01:35 PM
You could try doing something like this:
Suppose you have room A. each door is assigned a script that contains a Vector2:
the door on the bottom is assigned (0, -1)
the door on the left is assigned (-1, 0)
the door on top is assigned (0, 1)
the door on the right is assigned (1, 0)
Let's call this Vector2 nextRoomDir . When you build the rooms, you know their length - them being all the same size, as you mentionned.
When you open a door, you want the next room to be instantiated at position: currentRoomPosition + roomlength * nextRoomDir
using UnityEngine;
using System.Collections;
public class Door: MonoBehaviour
{
public int roomType; // roomA is 0, roomB is 1 etc.
public GameObject roomA;
public GameObject roomB;
public GameObject roomC;
public GameObject roomD;
public Vector2 nextRoomDir;
int roomLength = 5; //Change this to whatever your roomLength is!
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Player" && Input.GetKeyDown(Key.E))
openNextRoom(); //Considering each door has a trigger, door opens if the player is close to the door and is pressing the E key.
}
void openNextRoom()
{
float nextRoom= Random.Range(0, 3);
if (roomType == 0){
if (nextRoom>2)
createNewRoom(roomD);
else if (nextRoom>1)
createNewRoom(roomC);
else
createNewRoom(roomB);
}
else if (roomType == 1){
if (nextRoom>2)
createNewRoom(roomD);
else if (nextRoom>1)
createNewRoom(roomC);
else
createNewRoom(roomA);
}
else if (roomType == 2){
if (nextRoom>2)
createNewRoom(roomD);
else if (nextRoom>1)
createNewRoom(roomB);
else
createNewRoom(roomA);
}
else{
if (nextRoom>2)
createNewRoom(roomC);
else if (nextRoom>1)
createNewRoom(roomB);
else
createNewRoom(roomA);
}
}
void createNewRoom(GameObject roomToCreate)
{
Object.Instantiate(roomToCreate, transform.parent.transform.position + (nextRoomDir.x * roomLength, 0, nextRoomDir.y * roomDir), transform.parent.rotation);
}
}
This script probably isn't flawless but I hope it inspires you :)
Great idea for room generation. I was wondering on line 55 what the "roomDir" is referring to? It is definitely inspiring. As stated below in my comment I am having a hard time finding resources on how to instantiate random rooms to a grid node type system. Everything I find an abundance of whole dungeons but no room generator
Answer by UNDERHILL · Aug 23, 2016 at 05:14 AM
here's one way I did this you need prefabs which are about what they sound. Room has a door n s e w don't try to run this, it's just for example
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class NewRoomSpawner : MonoBehaviour {
//needs to not parent doors to room because this causes issues with animations
//wDoor eDoor etc basically need to have no parent so they will animate in place?
public enum RoomType
{
RoomTypeEmpty,
RoomTypeEmptyAttic,
RoomTypeEmptyBasement
// RoomTypeArboretum,
// RoomTypeCrystallium,
// RoomTypeHubbardium
}
public enum Statues
{
StatuesDragon,
StatuesGargoyle,
StatuesLion,
StatuesNefertiti
}
public enum Trees
{
Broadleaf_Desktop,
Palm_Desktop,
Conifer_Desktop
}
void OnMouseDown()
{
RoomType randomRoomType = (RoomType)Random.Range(0, 3);
Debug.Log("random roomtype: " + randomRoomType);
Vector3 roomCheck = placeRoom(gameObject.transform.parent.gameObject);
Debug.Log("checking for existence of room named: " + roomCheck);
if( roomCheck != new Vector3(0,0,0) ) //check for the zero vector return value which indicates the room exists
{
//create the room
GameObject theNewRoom = createRoom(placeRoom(gameObject.transform.parent.gameObject), randomRoomType);
Debug.Log(theNewRoom.GetComponent<Collider>().bounds.size);
}
else
{
Debug.Log("did not create new room");
}
//open the doors
openDoorsInRange(gameObject.transform.position, 5.0f);
Debug.Log("Opened doors at: " + gameObject.transform.position);
} //onmousedown
//HELPER FUNCTIONS
//placeRandom returns a random Vector3 offset for use in placing objects at random locations within rooms
//specify any coordinate to override
public Vector3 placeRandom(int x = 0, int y = 0, int z = 0)
{
if (x == 0) { x = Random.Range(-11, 11); }
if (z == 0) { z = Random.Range(-11, 11); }
return new Vector3(x, y, z);
}
//openDoorsInRange does exactly that
public void openDoorsInRange(Vector3 pos, float range)
{
Collider[] colliders = Physics.OverlapSphere(pos, range);
foreach (var col in colliders)
{
if (col.GetComponent<Collider>().tag == "door")
{
col.transform.parent.GetComponent<Animator>().enabled = true;
}
}
}
public bool randomBool()
{
int randomNumber = Random.Range(0, 100);
return (randomNumber % 2 == 0) ? true : false;
}
public void spawnDoors(Vector3 loc, GameObject doorParent, bool nDoor = true, bool sDoor = true, bool eDoor = true, bool wDoor = true)
{
List<GameObject> newDoors = new List<GameObject>();
//randomly choose not to spawn doors
// nDoor = randomBool();
// sDoor = randomBool();
// eDoor = randomBool();
// wDoor = randomBool();
if (nDoor)
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/nDoor")));
newDoors[0].name = "nDoor";
//newDoors[0].transform.parent = doorParent.transform;
newDoors[0].transform.localPosition = loc + new Vector3(4,loc.y,-12);
}
else
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/nNoDoor")));
newDoors[0].name = "nNoDoor";
//newDoors[0].transform.parent = doorParent.transform;
newDoors[0].transform.localPosition = new Vector3(0,loc.y,-4);
};
if (sDoor)
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/sDoor")));
newDoors[1].name = "sDoor";
//newDoors[1].transform.parent = doorParent.transform;
newDoors[1].transform.localPosition = new Vector3(-4,loc.y,12);
}
else
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/sNoDoor")));
newDoors[1].name = "sNoDoor";
//newDoors[1].transform.parent = doorParent.transform;
newDoors[1].transform.localPosition = new Vector3(-4,loc.y,12);
};
if (eDoor)
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/eDoor")));
newDoors[2].name = "eDoor";
//newDoors[2].transform.parent = doorParent.transform;
newDoors[2].transform.localPosition = new Vector3(-12,loc.y,-4);
}
else
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/eNoDoor")));
newDoors[2].name = "eNoDoor";
//newDoors[2].transform.parent = doorParent.transform;
newDoors[2].transform.localPosition = new Vector3(-12,loc.y,0);
};
if (wDoor)
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/wDoor")));
newDoors[3].name = "wDoor";
//newDoors[3].transform.parent = doorParent.transform;
newDoors[3].transform.localPosition = new Vector3(12,loc.y,4);
}
else
{
newDoors.Add((GameObject)Instantiate(Resources.Load("Doors/wNoDoor")));
newDoors[3].name = "wNoDoor";
//newDoors[3].transform.parent = doorParent.transform;
newDoors[3].transform.localPosition = new Vector3(4,loc.y,0);
};
}
//placeRoom returns a new room location based on the name of the door parent passed to it (named in scene wDoor, eDoor, etc...)
//change placeroom to simply use an offset of the door position instead of the room parent position
//doors need to not be children of rooms which probably means placing them using world coordinates which they might be already
// public Vector3 placeRoom()
// {
// Vector3 doorLocation = gameObject.transform.position;
// }
public Vector3 placeRoom(GameObject doorParent)
{
//Debug.Log("PlaceRoom called and forward is: " + gameObject.transform.forward);
Debug.Log("PlaceRoom called and doorParent.name is: " + doorParent.name);
//get the name of the parent of this door
string thisName = doorParent.name;
//position of ultimate parent object for placement of the next
GameObject nextRoomParent = doorParent.transform.root.gameObject;
Debug.Log("Next room parent is: " + doorParent.transform.root.gameObject);
//initialize a possible position for the new room
Vector3 nextRoomPosition = nextRoomParent.transform.position;
Debug.Log("(this room position) nextRoomPosition: " + nextRoomPosition);
//decide an appropriate new position for the next room
switch(thisName)
{
case "nDoor":
nextRoomPosition += new Vector3(0,0,-24);
Debug.Log("ndoor" + nextRoomPosition);
break;
case "sDoor":
nextRoomPosition += new Vector3(0,0,24);
Debug.Log("sdoor" + nextRoomPosition);
break;
case "eDoor":
nextRoomPosition += new Vector3(-24,0,0);
Debug.Log("edoor" + nextRoomPosition);
break;
case "wDoor":
nextRoomPosition += new Vector3(24,0,0);
Debug.Log("wdoor" + nextRoomPosition);
break;
default:
break;
}
Debug.Log("PlaceRoom result: " + nextRoomPosition);
//construct what the new name would be if this room were created
string nextRoomName = nextRoomPosition.ToString("F3");
if(GameObject.Find(nextRoomName) != null)
{
return new Vector3(0,0,0); //this result needs to be checked for by the caller and might need to be 999 999 999
}
else
{
return nextRoomPosition;
}
}
public GameObject createRoom(Vector3 pos, RoomType type)
{
GameObject obj = new GameObject();
switch(type)
{
// case RoomType.RoomTypeArboretum:
// obj = createRoomArboretum(pos);
// break;
// case RoomType.RoomTypeCrystallium:
// obj = createRoomCrystallium(pos);
// break;
case RoomType.RoomTypeEmpty:
obj = createRoomEmpty(pos);
break;
case RoomType.RoomTypeEmptyAttic:
obj = createRoomEmptyAttic(pos);
break;
case RoomType.RoomTypeEmptyBasement:
obj = createRoomEmptyBasement(pos);
break;
// case RoomType.RoomTypeHubbardium:
// obj = createRoomHubbardium(pos);
// break;
default:
break;
}
return obj;
}
private GameObject createRoomHubbardium(Vector3 pos)
{
Vector3 nextRoomPosition = pos;
string newRoomName = nextRoomPosition.ToString("F3");
Debug.Log("Placing Hubbardium at: " + nextRoomPosition);
GameObject nextRoom = (GameObject)Instantiate(Resources.Load("Room"));
nextRoom.transform.position = nextRoomPosition;
nextRoom.name = newRoomName;
spawnDoors(nextRoomPosition, nextRoom);
GameObject device = (GameObject)Instantiate(Resources.Load("Batteries/Prefabs/Battery_small_06"));
device.transform.parent = nextRoom.transform;
device.transform.localPosition = new Vector3(0,0,0);
device.transform.localScale = new Vector3(0.5f,0.5f,0.5f);
Light newLight = nextRoom.AddComponent<Light>();
newLight.color = Color.cyan;
newLight.intensity = 8;
GameObject spray = (GameObject)Instantiate(Resources.Load("WaterFX/Prefabs/SteamSpray"));
spray.transform.parent = device.transform;
spray.transform.localPosition = new Vector3(1,-2,7);
spray.transform.Rotate(90, 0, 0);
nextRoom.AddComponent<Hubbardium>();
return nextRoom;
}
private GameObject createRoomEmpty(Vector3 pos)
{
Vector3 nextRoomPosition = pos;
string newRoomName = nextRoomPosition.ToString("F3");
Debug.Log("Placing Empty room at: " + nextRoomPosition);
GameObject nextRoom = (GameObject)Instantiate(Resources.Load("Room"));
nextRoom.transform.position = nextRoomPosition;
nextRoom.name = newRoomName;
spawnDoors(nextRoomPosition, nextRoom);
return nextRoom;
}
private GameObject createRoomEmptyAttic(Vector3 pos)
{
Vector3 nextRoomPosition = pos;
string newRoomName = nextRoomPosition.ToString("F3");
Debug.Log("Placing Empty Attic room at: " + pos);
GameObject nextRoom = (GameObject)Instantiate(Resources.Load("RoomAttic"));
nextRoom.transform.position = nextRoomPosition;
nextRoom.name = newRoomName;
spawnDoors(nextRoomPosition, nextRoom);
return nextRoom;
}
private GameObject createRoomEmptyBasement(Vector3 pos)
{
Vector3 nextRoomPosition = pos;
string newRoomName = nextRoomPosition.ToString("F3");
Debug.Log("Placing Empty Basement room at: " + pos);
GameObject nextRoom = (GameObject)Instantiate(Resources.Load("RoomBasement"));
nextRoom.transform.position = nextRoomPosition;
nextRoom.name = newRoomName;
Vector3 doorSpawnLoc = nextRoomPosition + new Vector3(0,-8,0);
spawnDoors(doorSpawnLoc, nextRoom);
Debug.Log("Spawned doors for basement room at: " + (nextRoomPosition + new Vector3(0,-8,0)));
return nextRoom;
}
private GameObject createRoomCrystallium(Vector3 pos)
{
Vector3 nextRoomPosition = pos;
string newRoomName = nextRoomPosition.ToString("F3");
Debug.Log("Placing Crystallium at: " + pos);
GameObject nextRoom = (GameObject)Instantiate(Resources.Load("Room"));
nextRoom.transform.position = nextRoomPosition;
nextRoom.name = newRoomName;
spawnDoors(nextRoomPosition, nextRoom);
for(int i = 0; i < 20; i++)
{
//Debug.Log("Loop");
Vector3 chooseCrystalPos = placeRandom();
float chooseCrystalHeight = Random.Range(1, 8);
Vector3 crystalBaseDimensions = new Vector3(1, chooseCrystalHeight, 1);
GameObject newCrystalBase = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
newCrystalBase.transform.localScale = crystalBaseDimensions;
newCrystalBase.transform.parent = nextRoom.transform;
newCrystalBase.transform.position = chooseCrystalPos + nextRoomPosition;
Renderer rend = newCrystalBase.GetComponent<Renderer>();
rend.material.color = Color.black;
rend.material.shader = Shader.Find("Specular");
rend.material.SetColor("_SpecColor", Color.blue);
GameObject newCrystal = (GameObject)Instantiate(Resources.Load("Crystals/crystal1"));
newCrystal.transform.parent = nextRoom.transform;
chooseCrystalPos += new Vector3(0, chooseCrystalHeight + 0.5F, 0);
newCrystal.transform.position = chooseCrystalPos + nextRoomPosition;
}
return nextRoom;
}
private GameObject createRoomStatuary(Vector3 pos) {
return new GameObject();
}
//private GameObject createRoomArboretum(Vector3 pos)
// {
// Vector3 nextRoomPosition = pos;
// string newRoomName = nextRoomPosition.ToString("F3");
// Debug.Log("Placing Arboretum at: " + pos);
// GameObject nextRoom = (GameObject)Instantiate(Resources.Load("RoomAttic"));
// nextRoom.transform.position = nextRoomPosition;
// spawnDoors(nextRoomPosition, nextRoom);
// nextRoom.name = newRoomName;// //place a number of trees within the room
// for(int i = 0; i < 10; i++)
// {// //this needs to be case with a type because this way creates tons of blank gameobjects - i think
// //this is because of the way 'if' works with existing objects
// GameObject newTree = new GameObject();// Vector3 chooseTreePos = placeRandom();
// int chooseTree = Random.Range(0, 3);
// if(chooseTree == 0)
// {
// newTree = (GameObject)Instantiate(Resources.Load("Trees/Broadleaf_Desktop"));
// }
// else if(chooseTree == 1)
// {
// newTree = (GameObject)Instantiate(Resources.Load("Trees/Palm_Desktop"));
// }
// else if(chooseTree == 2)
// {
// newTree = (GameObject)Instantiate(Resources.Load("Trees/Conifer_Desktop"));
// };// //set the parent
// newTree.transform.parent = nextRoom.transform;
// //place the tree
// newTree.transform.position = chooseTreePos + nextRoomPosition;
// Vector3 treeBaseDimensions = new Vector3(2, 2, 2);// //add a base
// GameObject newTreeBase = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
// newTreeBase.transform.localScale = treeBaseDimensions;
// newTreeBase.transform.parent = nextRoom.transform;
// newTreeBase.transform.position = chooseTreePos + nextRoomPosition + new Vector3(0, -1, 0);// Renderer rend = newTreeBase.GetComponent<Renderer>();
// rend.material.color = Color.grey;
// rend.material.shader = Shader.Find("Specular");
// rend.material.SetColor("_SpecColor", Color.grey);
// }// return nextRoom;
// }
}
Answer by technorocker · Jul 02, 2018 at 06:36 PM
What a great idea @UNDERHILL. Ive been looking for something along this line for quite some time actually. I'm trying to build a board game type where players on a grid explore the board and rooms are generated as they open each new door adding it to the map. I have a grid system that makes each grid node the size of the room generated. I am currently making whole static rooms as prefabs and was wondering how I could instantiate each room to a center of each node as it generates. Plus each room has different number of doors always places at the center of each side of room. Any help would be much appreciated.
I'm still new to development and this is my first attempt at my own game. I ahve done many online courses thus far but have yet to come across individual room generation as oppose to the multiple dungeon generators.
For lack of resources to be found I did find this post https://answers.unity.com/questions/711778/adding-prefabs-to-a-list-or-an-array-from-a-folder.html
which allows for a list of prefabs to be generated. It was meant for generic objects but I tested it out and can instantiate well... I just cant figure out how I would make the doors line up to the previous room door properly.
As you hit me back 2 years after the fact, and I didn't see it until 2 years later, I'll hit you back with some images of what I've been working on the last few days that brought me back here... https://imgur.com/a/S6$$anonymous$$XAhv
Your answer
Follow this Question
Related Questions
Picking up an item and spawning a new one. 0 Answers
Is Random.InitState's Seed's random generated numbers change computer to computer? 0 Answers
How to tell if the code flow changed 2 Answers
Beginner trying to set up random variable for game + and then some. 2 Answers
Random Generator Instantiate Tiles C# = PLEASE HELP = 0 Answers