BrandGhost

RPG Dev Log 1 - Persist Game Objects Across Maps

Kicking off this first RPG dev log with an interesting challenge I was finally met with today! This is nearly 40 minutes of me explaining some of the game architecture present today and live problem solving how game objects can persist. To elaborate, maps in the game when loaded will place things such as static tiles (i.e. the ground you walk around on) as well as the game objects you interact with. However, many of the game objects are defined in the maps as templates (i.e. a definition to cre...
View Transcript
so i wanted to do a little devlog on a i guess a current uh challenge i'm facing with a part of this game that i'm trying to put together with some friends and i figured uh not only would this be kind of a cool way to uh to get a video up on youtube but also just to kind of help me troubleshoot something i'm genuinely debugging right now which is a i think an interesting problem um so we're putting together a role-playing game and i'm about to play um a pretty rough version of it uh the graphics and stuff totally suck but the challenge i'm kind of facing right now is that we have these maps that the player can walk around on and when the maps load up they have some placeholders for things to to be generated and appear and then i guess as we transition from one map to the next i need to be able to carry some game state to the next map so as an example uh i guess the the primary concern is like the player right so as the player is placed onto a map i need to make sure that that player exists on the map but as he goes to the next map that this player state is is realized right so if you pick up items or you do something on a particular map and you go to the next one you shouldn't just have a whole brand new player you should have the same player you've been working with so i'm going to press play do keep in mind graphics are rough it's still there's a lot of stuff sort of in the game engine behind the scenes but we don't have much in unity so it looks pretty trashy um so you'll see there's a couple ugly things going on but what just happened was when we started the game um we were able to load up a map file from i'm using we're right now we're using this tmx open map like tile map format it's just a i guess an interim kind of thing we haven't designed actually how we want to store things but this kind of got us going and when we load up the tmx it has some placeholders for different things so first is i guess all the tiles that you you kind of see in the game world here um these are all um kind of placed in this tmx file and then where you see all these uh kind of ridiculous uh colors squares this information is also defined in the tmx file so kind of defined per map and these are actually just placeholders and it's like when we're in the game debugging things it's really nice to visualize where these transparent things are uh so you know those get generated from the map and even it's not it's probably not the right way but just for testing the player is actually defined as part of the map the unique thing about this and by the way this is it's placeholder rain coming down i know it looks terrible we just wanted to prove that we could have weather that changes in the game so apologies for what that looks like but it's pretty low quality um so anyway um the like generally how this works is that we want to have the map have um i guess like we call them like spawners so things like a region or a point that will spawn uh other content and this is because we want to be able to dynamically create things for the most part right so if you imagine that as an example you show up on this map and you go oh look there's a chest over here um we want to be able to have some type of procedural generation some type of randomization where you can go to that that chest and it will give you random loot so we need to be able to place a chest we need to be able to let that generate things maybe instead of placing the chest directly we would place something like a spawner that could spawn a chest or it could spawn maybe on the ground instead of a chest you could have a particular item that you could pick up but anyway these the spawner is essentially like a concept that will allow us to like create a new instance of something on the map kind of conversely to that we have this concept of templates and actually this chest is a particular template so instead of this being defined on the map as its own unique instance of this chest it's actually defined on the map such that it is a template when we load this map if we come across templates defined on the map we replace like as we load the map into memory anything that's a template we kind of create a new instance of that object from the template this just gives us a shortcut for kind of predefining certain properties so as an example this chest we use this particular animation for this chest um this it's not currently supported but if we wanted to say like spawn a locked chest is you know wooden with metal on it like we could use that as a as a template if you're used to unity this is kind of um similar to a prefab we just do a lot of behind-the-scenes work that unity kind of does for you but we do it so that it's unity agnostic so just to kind of reiterate quickly something like this chest that we have in the game is made from a template we have spawners that can place content into the game world and then also like this player actually the player right now as a template is also a bad example but you can you can have um like technically unique uh identifiers for an actual saved instance of something but this is kind of it's not really supported yet and that's kind of this next challenge that i'm working through so really what we're trying to do is get um uh like the base flow of having a combat scene uh you know progress and and then you kind of go on to the next map so this works just like pokemon i have this big red box down here and this red box is gonna allow us to enter an encounter uh randomly so you kind of it's like long grass and pokemon you just walk around on it just to start we have randomized encounters um so you know i can walk around on this yes the player is behind it's just it really doesn't matter we're just using it as a placeholder and you can see that randomly i ended up going into this encounter so we've joined a new map yes it looks identical because i just copied and pasted it but what you'll notice is where we used to have these uh magenta squares we actually have skeletons that have spawned right so there used to be a bunch of magenta squares i actually was placed i as in the player here was placed at one of those magenta squares and then these skeletons three of them were spawned at over top of these other magenta squares so the magenta squares are actually spawn locations right so that's kind of what i was getting at with uh the the spawners so these spawners were configured such that they could have a skeleton appear and those skeletons are created from a template but now that they're created each of these skeletons is its own unique object right so they were created from a template so we could copy some settings but they're all their own unique objects so as an example the skeleton that i'm highlighting right now might have id a this one might have idb this one might have idc my player has its own unique identifier and that's all great so what we want to be able to do is have combat progress right now it's pretty busted so um if i try to progress it technically the i can't ever win this fight the skeletons will kill me um but if i could win what we want to be able to do is um you know allow the player to exit the combat we call them encounters so they can exit the encounter and then we want to put them back on the map that they were walking around on before and the challenge is that as we transition between these maps our game objects are only stored like once they become their own unique object from the template they're only stored on the map so it's a little bit hard to conceptualize especially because i'm pointing at some some squares with some skeletons and a little dude on it um so i'm going to end up drawing a picture and paint in a second here but the the challenge is that once we create things from a template we don't have a good way to to kind of carry like to persist that information from map to map so i'm going to kind of talk about my initial idea again this is literally a problem i'm trying to solve right now so i don't actually don't have a solution for it but i'm going to kind of walk through what i think might be a reasonable approach to this talk about something i actually don't really like about it and maybe as i'm going through that i'll come up with another idea but anyway that's kind of the gist of what happens on here and again the thing we're trying to solve is that i want my character to have some state and as he goes from map to map i want that state to persist um sounds pretty simple i guess on the surface if you're thinking about oh there's only this one player um that you want to have some state persist technically um we're trying to make it generic so that any game object can technically move between maps um we do plan on having this be party based so you could have we don't know how many yet but say you have four actual characters um that's already four game objects that are player controlled that we need state to persist between maps um so really just coming up with the generic framework that lets us um you know go from loading up templates to having unique instances to to kind of persisting that to use on other maps so i'm going to try and stop this i'm going to try to to draw something in paint here and we'll see what i can come up with so my drawing is not so great but i'll kind of walk through it and i'm probably gonna um flip back and forth here between um paint and visual studio so i can double check that uh you know i want to be able to kind of illustrate the things i'm looking at i'm losing my cursor here because my monitor is pretty big um okay so what i want to do let's see if i can get a slightly larger brush here um that's not there we go so what i want to do is kind of draw some of the things going on so right now what's happening is we have a a tmx file and that's what our map is right that's what i was saying so that's a a map we have this tmx file and within the tmx file not only do we have all of our tiles and stuff listed but we have some some spawners or or templates for objects generally ideally they are spawners so we can be dynamic as possible but you could imagine that we might have a say a particular town or something it's always going to be structured the same but we want some things to be dynamically created um so generally we have templates or spawners so i'm going to put um you know t one t 2 that is a 2 i know it doesn't look like it but trust me it is there that's a 3. um so we're going to have this tmx map this is sort of persisted on disk here's that's how we define the maps and just to show you one quickly i'm gonna pull up um our game code here there's a lot of stuff going on like i said there's a lot actually happening in the game this is only uh one of the solutions that has has 58 projects i think the other one has 100 and that's not even unity stuff so um kind of going to jump to the content here going to open up one of these maps this is a tmx map format so it's kind of weird to look at with your like to read you're supposed to use a tool for it but if i jump to the bottom um you can see that i have this section where there's these game objects defined right so the stuff we're interested here's the player as an example you can see that it has a template id called player as i mentioned this one's a bit of a poor example uh the reason why is that we don't want to load a map and create a player from a template we probably want to go through some character creation kind of stuff um but anyway this is just kind of for testing there's a bunch of static game objects that are just walls so they are invisible colliders uh the template that they use is literally just called wall it's invisible um you know these names will change and stuff but this is kind of so that we can do collisions and stuff on the map um you can see that that chest i was talking about is defined here right um and then we're going to want to have things like spawners so um i kind of lied when i said that those things before were spawners they're actually spawn locations so you can see here those magenta tiles are actually called encounter spawn as a template id so those are locations that the um the enemies and the player and players teammates can spawn at so as we're loading up that map we can kind of place things anyway here's the tmx map format just wanted to kind of give you a quick look at what this is right now this is the format we support but like i said we're probably going to switch it to something else it's pretty heavy to have that simple map has like you know 20 000 lines we'll probably make our own map editor in unity but anyway so we have the the tmx map file and basically what's happening is that when we want to load something so we want to switch a map i'm not going to type or write everything out so we want to switch a map i should probably switch to that text box when we want to do that what we're actually doing is we ask for all this data we pull it all in and so we're kind of pointing at which map it is so quickly right so we ask for a map id and then we're going to read in all this data and as we do that um we're going to um build the map tiles out so that's kind of like the grass and that weird looking water that you probably saw so we layer all that out and then [Music] we're going to load the game objects in and that loading of the game objects if i just flip back to um the visual studio really quick that's this section this where it says object group right so um the way we handle that is that we have a uh we use the facade pattern a lot so we have a facade that has uh it's basically like a repository and a facade put together or a factory and a facade put together i guess and based on the type of template we have different things that can handle that so i'll use the the player as an example right you can see that it has template id player if i go to actor template repository this is all kind of injected behavior into here but um actually this one we want a little bit more extreme so i need to actually go to the player factory player template repository sorry yeah so i was starting to code up some stuff here then i figured i'd make a video about it so ignore this for now we'll come back to it we have a player template repository it is able to handle the template called player which um like we saw right that says player for the template id um and then from there uh not to explain everything that's kind of going on up here but um you know we create a player object um it's a new instance of one you know we're not going to a database to do anything we're not reading it from other files we're kind of just setting up a player placing him on the world here and that's it but now by doing that we've created a new instance of a player and if you can think about this for a second anytime we go to this map so i'm just going to write this currently this includes the player right so um if you think about that we end up going from you know we've made maybe i shouldn't use a square for that um i don't know like a circle like we got a this is some action we're doing so we're going to pull this stuff in and then what we end up getting i'm going to draw it back this way why did i do that i don't want a line give me my brush um sorry yeah so we're going to do all that stuff and then technically so this was on disk like i mentioned this part is going to be in memory we have a map and then we actually have [Music] now we have the the tiles that you can see there are no spawners right because by doing this action here this circle this is where we're taking templates and spawners and everything and making them instances so there's no spawners no templates and then it has i guess like object instances right so this is why this is a little bit tricky and i kind of try to put it all together pretty quickly here so anytime that we get you know we load up a map we've created these instances now anything that happens in the game while it's running um that mutates these instances so as an example i mentioned like if the player picks up loot or you know you level up your character the player has some state that changes if we go to the next map and say the next map just happens to look like this one over here right if it happens to be this map all that we're going to do is blow this part away we're going to go do this whole process again and create new instances of all those objects and the reason why is because we're going to be going from templates and spawners and regenerating all that stuff so i actually need to come up with a way that says after we've created some of these things so we've say we've created the player or like when you saw that i created the skeletons that's a poor example because it's only in combat but the the chest right if i wanted to dynamically create the chest that we were able to see in the game i need to come up with a way that i can say the next time i come back to this map i want that particular chest to be there um with the player i want to say um here's you know we've created an instance of the player i need that player to persist through the you know the different maps that we're going to but currently we can't because the only spot that we get data from is on these maps which has been useful so far but when you actually want to start playing the game and building upon it um you know that's kind of the bottleneck right now that i'm i'm dealing with so um i kind of left out like how does this part work just use a different color like i just said it happens i mentioned there's a repository or i guess a factory in this case and like a facade pattern so we quickly looked at one of the the facades sorry one of the things behind the facade um calling it a template repository uh the names are a little bit in flux right now uh you'll notice like i mentioned i just added this this should actually be like player template factory now um because it's not actually getting anything from like persisted uh anyway that's just a quick renaming thing that was happening like i said i'm in the middle of it so um because we're pulling everything from this uh tmx file right now uh and using a factory to create new instances of things every time i need to find a way to get that to persist so um the current idea that i have and not totally sold on it and haven't totally figured it out but when we go between maps i want to like the first thing that came to mind is like i need to persist this so when i say the word persist the first thing that i think of is like i got to write this to disk um i was like you know on the surface that seems like i think kind of crappy um you know i just made this map i i don't even know if i um like does the player want this information to be saved to their game um like what if they haven't saved and they want to you know reload and i've gone ahead and i've uh you know i've saved this map information and like and where do i save it right do i go overwrite this tmx map uh probably not because um that's game content and i probably need to anything i'm saving to disc i need to find a spot to put it i need to make that part of like the players save game so we have none of that right now um but the first thing was like i need to persist it and i should write it to disk so um then i was like okay like that feels a little bit like overkill um there's a lot of things we haven't figured out yet for what type of storage we want to use you know there's a whole lot to think through on that how we want to serialize certain things so i was thinking okay if that's the let's say that's the direction we want to go we need to be able to persist stuff and i don't know how deep i want to go on that yet my thought was well what if i take these object instances that we see here right um what if i can take those and when we switch maps i can uh you know i'm going to use air quotes i save them out and by save i mean i'm just going to put them in a dictionary keyed by their their type and their identifier technically the identifier we would like it to be you know like a good or something like something that's globally unique it's not enforced right now so it has to be unique at least for the type of object that it is but anyway we key it in a dictionary by its identifier and then when we want to load it we would basically just go to the cache in memory like basically cut out the whole uh convoluted part that i haven't figured out of how we want to persist it to disk and just use a in memory cache like a dictionary so what that kind of looks like let me get rid of that there um what that kind of looks like is then we want to um do this switch map thing again right so i'm going to i'm going to get rid of that and we want to so we want to do this action to switch map i just wanted to redraw it i don't even know how i want to draw this yet um but when we switch a map um because in the initial state like technically it didn't have a map open but i want to kind of reuse this so um if we have a map already open and we want to switch what that's going to look like is i need to tell i need to tell this give me all of your object instances maybe i'll use a different color for this so this is going to ask this thing give me all of your object instances right we're going to take those back out i'm going to put them into a um really just like it's a dictionary um right so i'm going to put them into this dictionary of objects by their id and then i would proceed with the loading of the map file and i guess that's where that's it's as far as i got really and it already kind of falls down because when we go to load this map file like right now it's i mean up until like a couple hours ago basically i was reloading the same map file and just uh generating skeletons on it but it's the identical it's the same map file so i can kind of use it for this example just to prove a point that when i go to load this map now sure i might have cached all of these things in this dictionary right so that was great but um when i go to load from this map file the map itself was never saved right so i tell i say switch map and i'm going to put in map id a again um say this was a to begin with right it's going to go ahead and go do all this stuff again and do all the template um and spawner conversions um and it's not gonna know to pull from here so i feel like what i need to do and this is i'm literally thinking of this on the fly right now so i haven't fully thought through this idea is that if i'm gonna cash out these um game objects pretending like you know it's gonna make it look like it's saved to disk but just while it's running so i've cached these game objects maybe what i need to do as well is is actually cache like some type of object lookup for this map right because the tiles themselves aren't going to change i'm just going to jump back to visual studio here so i can point at this map file like the 20 000 lines above here they're not going to change right that's all going to be the same and really i just like i deleted just to make it easier to read but um really it's this stuff here so maybe what i need to do is when you load up a map and you want to transition away what i'll do is anything that um is a like a game object like this that gets created from a template now has a unique id associated with it maybe at that point um you know i'll have a another look up that's like when you go to load this map you'll say hey like does this other overridden game object uh table already exist for this if so use that instead i kind of like that actually so what that looks like is um not only when we say switch map do we write out these uh or we not write out we literally store this dictionary of game objects maybe at the same time um we say maybe i shouldn't draw that we go make another look up here and this is for the map a um yeah like i don't even is it just ids that i need because all these things are gonna have a world location associated with them so um yeah like maybe that's all it is right so let me just get this back here so we go write this out right so we write that we write that and then the next step i'm going to use green now is we say we want to load map right so this is going to be a circle because it's an action um yeah i know this isn't proper convention for anything and i'm using paint to try and dry draw a bunch of lines here so uh bear with me um so now that we've we're switching the map we're going to write out i say right but we're going to store this information right now it's just in in memory but some other tables that we can look up and then we're going to switch the map and when we switch um what we can do is say oh you want uh map a right okay so like um have we come across uh i shouldn't have done that um say map a and then we'll say hey look does it have a lookup in here oh it does so like we'll we'll use this instead we're not going to use um the templates and basically going to jump back to visual studio here we're not going to use this um you know the predefined stuff in the tmx file and why it's because we've already been to this map it already like technically the map is going to have some state um what i'm trying to kind of suggest here is that once we've been on the map if you want to go back to the map you don't need this stuff you actually want the the stuff that i'm you know talking about written out over here so you don't use that you want to use this so we'd pull all the tiles right the tiles don't change we pulled the static stuff off the map and then what we would do is basically load so you'd i didn't draw this properly but you'd pull um right so i'm just gonna write what we're doing is pulling tiles from tmx and objects and objects from cache so that's a little bit convoluted um and if instead of switching maps we went to map b just to kind of show you um i picked that's funny i picked blue because i said b um yeah so just to show you a different example here so if when we go to switch map if we're not going back to a which we've already been on um and say we're doing b um we would go here to check hey like do you have a lookup already and like no it doesn't so then then we have to go i guess all the way back up to the t that's a terrible line um so no it doesn't we would go all the way back up and essentially what happens is we need to load all tiles from and then do templates and spawners right because b had never actually been loaded up it doesn't actually have this information available we have to go back to the definition of the of map b which is in the tmx file so i kind of like this i think that if i can put the proper apis um around these red boxes i drew if i can put the proper apis there um then i can figure out when it makes sense to persist right so um what i mean by that is uh i kind of mentioned earlier like what if the player doesn't want to save the game they want they don't want their save state to kind of persist to disk they kind of want to blow away their save and restart where they last saved that kind of thing if i put some decent apis around these red boxes here um we can basically decide like persisting does not necessarily mean part of the player's save game we might want to persist some stuff just because we have too much in memory it might make sense to have a you know a almost like temp files or something right so all the game objects and stuff that are loaded up maybe we write them to disk temporarily and then when the player saves we take that stuff that's on disk plus whatever is currently in memory we mash it all together and make it part of the player save game that's you know down the line it's definitely coming it has to happen at some point to have saving and loading but um kind of what i wanted to get across here is like does this solve the problem of going from map to map and allowing some type of persistence and i think it does because this gives us an option to to check a it's basically a cache but um the api wouldn't necessarily be like to call it a cache it would just be like um like a lookup of some sort but um yeah we can say we've already been to this map it's already had stuff transformed right generated spawned so don't go to the tmx just go to what we have here it just so happens the first implementation is going to be you know in memory in dictionaries so i think that's going to work that'll be nice to basically go from uh you know walking around i don't know if the sound's going to play i don't want this the sound's really noisy we uh we did some i say we my my friend did some really cool procedural generation for sounds but they're all totally random and they all happen when we collide with containers so when i go to this chest i was able to find a bunch of loot so as i mentioned i'm changing the state of the player right like he has items on him um i just you know made a a socket pattern so like it's kind of like diablo 2 rune word so um you know he has some state associated with him and you know even furthermore i'm going to go drop this armor on the ground right so by doing that i've changed the state of the map i've changed the state of my player and what i'm suggesting is like you can see that the player has items in his inventory um i don't i wanna i'll just i was gonna use the the cheat code to start combat but i'll just walk around um so what you'll see is when i get into combat here i don't have any of that and the reason i don't have any of that is because none of it persisted so what that will everything we just talked about what will that i can't speak what that will allow there we go what that will allow is that um any state that the player had you know that's now in memory um it will be the same player that kind of moves from map to map instead of being regenerated based on the tmx file and not only that you'll remember that i dropped some stuff on the ground i dropped a piece of armor on the ground i would be able to because this is the same map i could go back and see it on the ground um so i think everything we just described is potentially going to work i think that's the path i'm going to try out at least to start and we'll see how things go thanks

Frequently Asked Questions

What is the main challenge you're facing in your RPG development?

The main challenge I'm facing is figuring out how to persist game state, particularly the player's state, as they transition between different maps. I want to ensure that if a player picks up items or changes their state on one map, that information carries over to the next map they enter.

How are you currently handling map loading and game object instantiation?

Currently, I'm using the TMX open map format to load map files, which contain placeholders for various game objects. When a map loads, it generates instances of these objects based on templates defined in the map. However, once these objects become unique instances, I need to find a way to persist their state across map transitions.

What potential solution are you considering for persisting game objects between maps?

I'm considering using an in-memory cache, like a dictionary, to store the unique instances of game objects keyed by their identifiers. This way, when switching maps, I can check if I've already been to that map and retrieve the necessary game objects from the cache instead of regenerating them from the templates.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload