Hi all, hope everyone is having a great weekend!
First post here, please let me know if this is not the best spot for this.
I’m working on a RE-style game with fixed camera angles, tank controls, inventory etc.
One of the main core systems in the game is the room system. Coming from Unity (8+ years), the setup in Unreal is a bit different that what I’m used to. I’d like to ask what’s the best way to do this in Unreal. Let me first give you a rundown of the system requirements, and show you what I done so far.
- A ‘Room’ basically is an isolated chunk/section of the game world/level. It has ‘doors’ that lead to other doors in other rooms, it has static geometry, collision, camera triggers, pickups, enemy spawns, event triggers, etc etc.
- Player can ‘interact’ with a door in a room, to goto/teleport to another door in another room
- The rooms must be setup in a way that’s friendly for multiple people to work on remotely without conflicts (i.e. I can be working on RoomA, artist can be working on RoomB at the same time, we both pull/push and our work is saved fine, no conflicts), in other words it can’t be a single “Map” in Unreal
- The game must know about all the rooms that are currently loaded, and each room knows about all the doors in it.
- During development we must be able to teleport to any door in any room via console cheats easily
What I’ve done so far is:
- Every room has its own map
- At the root of every room, there’s a ‘Room’ actor that has an ID (int), and TArray of ADoorTriggers
- Each door has its own ID (int) (relative to the room), and a ‘GotoDoorId’ and a ‘GotoRoomId’, that way any door can go to any door in any other room (which makes console cheats teleporting easy)
- Each door also has a FTransform to specify where the player spawns at
- In the Room’s BeginPlay, I do GetAttachedActors to get the Doors attached to the Room. This means that anything that a room has, must be a child of that root room actor
- In AMyGameMode’s BeginPlay, I do GetAllActorsOfClass ARoom, to get a reference to all the rooms (which are all set to “Always Loaded” streaming mode for testing things out)
- When the player interacts with a door, I query that door’s ‘GotoRoomId’, from there I query the ‘GotoDoorId’, and set the player’s spawn location accordingly.
Here’s a little demo video if you guys want to visually see what I’m talking about: UE4 Room Testing - YouTube
My main issues with this setup are:
Having each room its own Map and adding them all to the persistent level is awkward to work with, I’d have to set the correct ‘Current Level’ in the Levels windows before I start adding in new actors to that Map, and also parent them to the ‘Room’ root actor. If I forget to parent a door trigger to the room root, the game wont be able to find it. Is there a better way to register these doors? Maybe there’s a way to say “Get actors in Map” or something? Or maybe the doors just register themselves (on Door BeginPlay, just grab the game mode and register self?) but then I’d also need to set some sort of “DoorRoomId” in order for me to know the room this door is registering from…
Having ‘int’ as an ID for rooms is awkward, its error prone and doesnt play nicely with Unreal’s resources/asset management systems. I’d like a different sort of ID that I can just click on and it shows me all the possible room options. Maybe the ARoom actor implements PrimaryDataAsset and override GetPrimaryAssetId to use the Asset name as an ID?
Having ‘int’ as a local ID for doors is not much an issue since there wont be that many doors in a room and those IDs are local anyways.
Streaming…? I’m not really sure where streaming fits into all of this. My vision is foggy in that area particularly because rooms are not just meshes but they have other things that should persist eventually when transitioning between rooms, like if enemy die and you come back to the room, he should be left where he died. I’m thinking each room has a OnLeave/OnEnter events where they serialize/deserialize relevant information to them to keep things persistent? I’m hoping somebody clears this up for me a bit.
My question to you is: Is this a reasonable setup for this? What can I do to improve? Is there a better way to set all this up that you recommend instead?
Let me know if you have any questions or I missed to mention a detail in my setup.
I don’t require concrete code solutions obviously but just idea discussions and pointer to the right directions would be appreciated!
Thank you very much!