hi Tim, i am an inexperienced game designer who loves your RPGs and your channel has helped me a lot. thank you for being so generous with the knowledge you have gained over the years
Here is a tip: implement load/save as early as possible. So you can figure it out as you go along + you don't have to stress about it + it will not be a huge task to do. (And the same is true for mod support for the game)
Agree 100%. In fact I'm currently starting a new project and spent the last week building the I/O architecture and mechanics which includes loading game metadata, saving game state and mod support. Not fun to write but essential and something you want to get sorted out at the beginning.
I think the most important thing is to implement saving and loading as early as possible in development. It makes testing everything so much easier if you can save a specific situation and load it later.
Here's a strange behaviour I found with the save system in the original Kings Quest III. I was save scumming my way up a mountain late in the game (you could very easily fall off the mountain trail and die). Save scumming was the only practical way of going up or down the mountains without magic. I had a single save game file and was using F5 and F7 to quickly load and save the game (IIRC they weren't quick save/load, but brought up the save/load interfaces). I walked off the mountain path and accidentally saved the game despite being dead. It was possible to save the game after you were dead. I had just discovered this the hard way. This was very frustrating to a quite young me. I never played that game again. This experience taught me to always use multiple rolling saves so I always had something to go back to. These days I always create multiple saves and typically will run up against the maximum save game limit if the game has one.
A bit off-topic: I know people nowadays use the term "save scumming" all over, even in news publications, but it's actually the derogatory form of the original term, "save scrumming". The term comes from a sport called rugby, where they would do something called a "scrum" or "scrummage" which is basically a way for them to __restart a play__. But since there are a ton of people that aren't familiar with rugby, they auto-correct in their minds to something more familiar... like scum which doesn't make as much sense, unless you're insulting someone. However, as you mentioned, in the age of Kings Quest, Command and Conquer, etc, save scrumming was almost a must, especially if we were younger at the time.
@@KeiNovakNo, it's not. The term originated with players of roguelike games. Since roguelikes are built around permadeath, reloading a save to escape a mistake or reroll a random event is considered “scummy.”
Its funny how often there is no real reason to limit saves, the only game that had bloated over 100mb on some levels was crysis1(and i think it shwowed the size in the menu) and effectively your save limit was disk space
I immediately knew where this story was going once I read "I had a single save game file and was using F5 and F7 to quickly load and save the game". We've all been there lmao
This video reminded me how nice it is that Rust is both a performant systems language, and has an *extremely* straightforward serialization system in the form of the Serde library. In all cases I've used it, serializing a structure only requires you to annotate the struct as (de/)serializable, and the code generation does the rest. Serializing and deserializing is just one function call. But also that serialization is only the starting point, and there's much more to this topic than just that.
Serialization is the worst form of creating a save game you can chose of. It is easy to use and comfortable from a developers perspective. But it is not a good form of a players perspective. Reason: Every memory can have a bit flip. This leads to incorrect data being stored and the serialization technology is particularly susceptible to this. Such errors can accumulate. It is therefore better to store the data in a structured manner using non-serialized technology. This allows the data to be checked for plausibility and errors have less of an impact. I once had a save game in Total War : ROME that was created via serialization. This save game was a late save game in the game and it always caused the game to crash on the next round.
@@OpenGL4ever Surely you could add error checking to the serialized version too? I've kinda thought that modern filesystems would deal with single bits being flipped, but evidently not. Still, I'd rather come up with a proper system that can recover from errors in the final serialized data. That honestly seems more robust and easier to me than fixing the issues in random save/load functions.
Such a great video (and channel). There aren't enough tutorials around that go through the important high-level game design problems in detail like this. I definitely feel like getting clear on what your problem is is halfway to solving it - whoever originally said that.
Thanks for the video, Tim. It came at just the right time! I've been troubled by file I/O and my save game system for months, and took a break to focus on other things. This video has given me the motivation to dive back into it.
Oh my god this is so helpful. For the past month I'm learning how to do serialization for my unity project, and the moment I hear serialization my heart rate immediately went up :(
I don’t know how big of a feature it is, but I appreciate when RPG separate saves per-run, with manual saves, quick saves and auto saves being kept separate.
Sir i want to Thank you the way you explane the stuff. so everybody is able to understand, all so like you take your to explane. am lovin it. Thank you.
For loading I usually just read and parse the whole data from disk once and feed it into the load method for each class, and each class is responsible for picking the parts of the data that it cares about, so the method signature of all the load methods are basically the same. I like JSON (or whatever human readable format) as it makes it easier for people to go in and play around with the data, easier to debug/easier to get good bug reports as a tester can go in and look if some field has a bad value saved somehow, allows testers to modify their save manually to get themselves into a particular state they want to test (if you don't want to bother creating specific tools for that kind of thing), and it generally makes modding a lot easier.
It also provides better protection against a broken save due to a bit flip in memory. The data can not only be checked for plausibility during parsing, but can also be repaired at any time by the user. This type of savegame storage is therefore clearly preferable to serialization.
I loved the idea I saw in one of the later Tomb Raider games actually, I think it was Tomb Raider 3. Where you'd collect crystals that you could use to save your game anywhere aside from cutscene/checkpoint saves. It initially felt more restrictive than Tomb Raider 2's save anywhere mechanic, but it actually made saving feel important and like an in-game resource which then gave it a feeling of a meta-game as well.
Thanks for explaining the high level decisions you need to make for specific implementations with some examples. You explanation on how classes would implement save file IO is pretty much exactly how I was taught it.
I never even thought about things like this thanks this was very insightful and I had no idea I needed to learn about serialization to know where to start with saving and loading
Having worked in tech the last couple of millennia, I went the JSON route. It works really well at my early stage of development because when a test has had an issue on their machine, they can send me the file, and it's fairly easy to figure out what's gone wrong. The file size on my modest metroidvania is 30k, which isn't great (and i could probably get down by compressing), but save and load is actually still very fast. I save the game when you exit to the title screen, and I would say it's instantaneous, so if you're not writing out many megabytes of data, it will probably serve a lot of people's needs. Even better in c#, you get serialization basically for free so you just dump everything to a string and read write that (which has memory implications, but may be fine in a lot of applications). C# constructs my json into a series of structs, that each module knows how to hydrate into game state. It's really easy, flexible, trivial to add a subsystem, and human readable at the cost of memory and some efficiency which honestly you could even optimize out with a more efficient file writer if you really needed to, so would recommend.
JSON isn't the best (there are a few binary equivalent formats that would produce faster and smaller results while keeping the main benefits), but a save file that isn't 'fragile' is more important than maximum speed or space efficiency. If it comes down to it, you could always compress the result when you save it anyway.
@@GrandHighGamer Reading JSON is actually fairly optimised in .NET in terms of both speed and memory. It does come with certain assumptions, namely, its implementation is one of a depth-first and a single-pass forward-only reader. So even megabytes and megabytes of game state only need a few kilobytes at the JSON layer.
I love when I can save a lot, not anytime anywhere, but at least before big battles and anytime when you are idle, on map etc. and I like quicksaves too, for instance in First Person RPGs. Not a big fan of checkpoints, but depends on game. For example Crash Bandicoot did it well. Edit: I used to be a fan of password saves which generated a code based on your statistics as well as level progress.
Kind of the same for me, though checkpoints can have a massive benefit. I remember at least two good examples for that: Alien vs predator 1, I remember running through corridors after hardly defeating a very hard enemy. With aliens on my heel. Shooting at every movement, panicking because I knew if I died I had to do all the fight again. It increased the stakes by a lot, compared to the typical save, die, reload... Similar experience was in Operation flashpoint. Dashing over a meadow to avoid a tank. Heart pumping, hearing the damn thing shot, explosion nearby, ducking running uphill into the cover of the trees, another close explosion. Then some shots, more running, sweating like I was running myself. Feeling more save after getting some more distance between me and the tank.. and then stumbling over a speznaz lying in a bush, reflex shooting, ducking, hiding... It's very hard to reproduce that with save/load everywhere... But also if you have to repeat that the 6th time because bad luck or, even worse, a have crash, then you start hating it again :D
@@Glimmlampe1982 That's why i didn't like Alien vs. Predator 1. They fixed this issue in Alien vs. Predator 2. It's no fun if you have to replay a level scene over and over again because you die before you finish each time. It's true that it increases the thrill, but the downside is more serious. So it is a big no no.
Versioning. IMHO, versioning your stored data is super important so that when you read data, you can verify that it's a version which you understand, and if it's an older version invoke different load-state code than for the latest version. Especially when writing out data serialized to a stream, based on my experience I think it's very important that each class/module that has its own custom write/read object code writes out a version number as very first thing for future use while reading back the data. Better to ignore a version number when you don't need it, then to need it and not have it! For data stored in a textual version this is also important but for raw data serialization it's even more important because often the stream will otherwise not contain any tags / markers to indicate what each value means, which field it maps to, and perhaps not even what type it is and how many bytes in size! (Of course if you use something like Protobuf for data serialization then the Protobuf framework takes on at least part of the responsibility of versioning your data and tagging the fields, types, and data sizes).
Keeping a couple of autosave or quicksave slots too, that way one 'bad save' is potentially recoverable. In a way that's kind of the point of autosaves (within the RPG genre the video seems to focus on). If the player forgets to save or the game suddenly crashes, they're not out an hour of progress.
Hey there! Great video as always! I have to say though: I disagree that text data is easier to handle compare to binary. If anything, I think it's the opposite: whether you convert your data to JSON or binary, you STILL have to serialize stuff, that hasn't changed. Now when you read the data, if you went for text, it means you have to parse it. It isn't just slower, it's also more difficult. If I'm loading a binary data, I just have to read bytes, and assuming I know the order my fields appear in, that's fairly easy to do. All of a sudden if you've got text you have to parse EVERYTHING, and in fact you don't even know how long your data is going to be, so you can't rely on fixed offsets to switch from a section to another. There's nothing text can do that binary can't, they both involve serialization and deserialization of some kind, but what it comes down to is: do you really need your data yo be human readable?
Thanks for this overview, especially considering the depth of your experience. This is a topic that the theory seems simple on the surface, but still made my head spin when I thought of the details and what-ifs. I did get a little lost when you were talking about pointers but I figured it was a C++ thing. Thanks again.
Once, I was working on a game where we implemented an auto-save feature on a background timer. Prior to that, we only had a quit-save, during which we deliberately broke AI, knowing that it would restore to mostly-the-same state on load. We ended up with some really weird AI behavior bugs, with the auto save regularly breaking the AI mid game. Most of these bugs surfaced long after we made the auto save update, making it a pretty hard bug to get to the root of.
Now I know why I've put off save/load as a new Unity designer. My intuition was right. I'm almost ashamed that, when I was just a "gamer," my thinking was just "Yeah push F5, and it saves the game!" Thank you. This was one of the best.
Organization: I like a "player profile" option, to separate saves into character specific "folders". Its easier to abandon/pausing a character and switch to a new one, without getting a big messy list of old saves. Or if two people play on the same machine. And for a save slot, next to a screenshot, also showing some general state like level, location, maybe current active quest name.
@@Seanhmattsonit’s a bit overpunctuated but if I’m commenting shortly after upload you can bet imma say “Hi Tim, it’s us, everyone” or a similar variation 😊
You covered pretty much all of save/loading. I've never used saving raw memory using pointers myself though. But that does sound clever. The project I'm on now uses JSON with file versioning, so the loader knows what mods were installed at the time of save.
Wow. All the time during the video I was thinking about Bethesda games. Is it really possible to keep track of the precise position and orientation of every single interactable in-game-object present in each and every map of Skyrim, and still manage to have a usable save-load system both in terms of speed and file size? I mean, no wonder my Xbox360 couldn't manage it, back then, after one or two hundreds hours of world disarraying gameplay from my part! Thanks for your videos!
Their games are some of the few I had to purposely limit my saves for. Now it's become a habit to rotate through a handful of saves, even if they offer "unlimited" slots.
Bethesda games let you load the base game, and then layer 254 ESM/ESP formatted addons/mods on top. You might notice this is 1 short of 256: this is because mod slot FF is actually where Bethesda games store all mutated game state. Which is to say, a savegame in Skyrim is literally a mod that mutates the game state from default to whatever you've done and accomplished in game. Has many bugs, but IMO it's quite a clever approach.
@@billy65bob Yes, I guessed the save system for in-game-objects location and orientation had to be based on delta values of some sort vs the default initial state of the game world. At least that way the amount of data related to that aspect of the game world state, at any save, wouldn't reach its theoretical maximum until you've moved every single object you can move. I had no idea that, in order to implement such an approach, those games could use the same systems as mods, though: thanks for the info!
I know you said before you don't care about save-scumming, but as a player I was sometimes grateful to the designer when that choice was taken away from me. It's all too easy to optimize the fun out of your game when you press F5 every 10 seconds and reload after every setback. Of course I could just "not do it", but that's not how my brain is wired. In my game I have decided to lock the randomization in place before saving, so that save-scumming doesn't get you anything different. Some players hate it, some don't care, but there's no pleasing everyone I guess.
Thank you this was thought provoking! I've worked on games that use fixed order save/load serializers and your description still made me really think. Hearing you describe them in this way made me think we should have written all the data into some hierarchical dynamic data structure in memory and then serialized that thing sequentially. Kind of like the memento pattern. You could add CRC checking to the end of each module entry which would hopefully make serialization issues more apparent. Also the actual file manipulation should be quite fast since you can blast through the whole map writing binary data.
In Eschalon the save anywhere feature allowed for an exploit to save after damaging an enemy but right before relinquishing your "turn", so basically you could do infinite damage by savescumming
I'm currently starting a new project and spent the last week building the I/O architecture and mechanics which includes loading game metadata, saving game state and mod support. My current plan is to save game state using XML because its human readable, easy to debug, easy to edit and easier to version. Also game metadata (plus mod data) will be in XML so same I/O system can be used to read configuration. Haven't benchmarked XML in a long time so not sure if it will end up being performant. Which is why I built an entirely custom I/O architecture that provides the class load/save methods with a reader/writer interface plus a generic storage parameter. For XML the storage is an XML Element but I can write alternative readers & writers that in theory could be anything including a file pointer. Writing this kind of code isn't fun but is essential and something you want to get sorted out at the very beginning. If you try and implement or change this system later its a lot more work as you have to go through a modify A LOT of existing code.
Hey Tim, I was wondering what your thoughts were on the increase in game industry layoffs lately. What does this mean for the future of games? What would you say to someone who wants to get into the industry? EA recently talked about incorporating generative AI right after firing hundreds of employees. I am worried game companies are looking for more and more ways to outsource and reduce employees in an already competitive industry. What are your thoughts on game unions? Thanks for all of the great videos!
I am working on a couple of videos, on both terrible things that happening in the game industry as well as changes that are happening (and yeah, there is overlap there). Keep in mind my perspective on things is very long term, and I have heard "doom and gloom" prophecies for literally DECADES...things like "consoles are dead", "PC gaming is dead", "turn based combat is dead", "RPGs are dead", "single player games are dead", "all artists are being replaced by 3D scanning and modeling", etc. So I breaking things into two videos...just how bad are things really...and people need to expect and adapt to change, because it is NOT going to stop. Expect them in a few weeks.
I'd be really interested in hearing more about save systems from a design point of view. I'm designing a game currently that I want to be dark and serious, and one where the player seriously considers their options due to consequence. However, I'm worried a game with no custom saves, and only auto-saves might not be fun at all to play. What do you see as the pros and cons to letting the player save when they want to. In other words is save-scumming something to worry about, or just let be?
I'm actually implementing Saving/Loading right now. For me, the extensive work is in the UI, as I made the decision to have "save rooms" like Castlevania: Symphony of the Night since my game is a open-world action JRPG with the same view point. And I love JSON.
I usually prefer save anywhere systems when I play games but checkpoints aren't always bad if they are not too far appart. They help with my obsession with saving every 5 minutes. What I absolutely hate is saving systems where you have to spend a resource to save. Luckily not many like that around.
Save slots were used especially in the past, when storage space was still tight and DOS limited you to 8 characters for the file name and 3 for its extension. The save slot allowed the player to assign a longer name internally and usually also showed the date if it was done correctly. At the file system level, everything was saved in the same folder as the program data. You then had a file for each of the available slots. Nowadays, of course, none of this is necessary anymore and slotless savegames are much better.
Hi, Tim! You were talking about the technical aspect of loading and saving, I would love to hear your thoughts on the gameplay impact of different types of loading and saving.
The migration of files from a version to the next is always fun. Setting up a reeeeallly good testing suite is mandatory. Otherwise, the kind of esoteric bugs it can cause will drive you insane
for some reason I was expecting a video on Save scumming :D anyway, I personally found that Entity Component Systems are pretty handy when you need to serialize a state because they tend to stay very orderly and easy to read and write, as long as you don't use too many third party libraries that keep an internal states, like many AI libraries.
Much as I hate Bethesda, I think it's kind of cool that Save Games for Bethesda's games are literally just a mod. It's mod 255 (or FF) to be exact, if you ever wondered why you're restricted to 254 addons/mods of the ESP/ESM format. 10:40 The easy solution I used for this, was to put a EOF check inside every single loop or read of variable length (i.e. strings) - It's pretty obvious you messed up when the loop wants to read 1787571723 items (and EOFs) instead of say a more reasonable number like 206. Even if it doesn't bug out at the exact spot, it usually blows up close enough to the problem that I can quickly find the mismatched spot and fix it. That said, I don't think binary formats are very much in vogue anymore; quite likely that games these days would just serialise either a JSON file or a series of them, and then shove them into a compressed container if you're lucky. Which avoids the biggest problem with binary formats: inter-version compatibility.
That was very interesting. I always wanted to hear about save/load from a developer. I wish you also made comments on how you deal with encryption or whatever else you use to protect save games against tampering when saving on local disk. Also, some comments on cloud saves / sync would be interesting.
Useless complexity for offline games where hacks/mods arent a problem. If youre going for online leaderbaords, I've seen a indie dev periodically check and ban records that arent posted on the speedrun site.
Hey Tim! Question of the day: If you had to choose now, would you rather... Work on a game that becomes an instant cult classic and marks a generation but puts your studio at the edge of bankrupcy? Or... Make a basic bitch RPG that sells millions and your soul?
1:04 just a note here: be aware that some low level language specific serialisation libraries don't promise to be compatible between versions. Off the top of my head though, I only remember gob in golang suffering from this. I don't remember if pickle in python is more stable or not.
What I didn't realize when I started developing my game is that there's no point in development where you can "relax" about saving, it's constant consideration about what needs to be saved and how to save it. You might think your save system works well until you realize "Wait, can I actually save when X feature is active?" and often you realize the answer is "no" and you have to refactor stuff so it can. That's why I prefer the approach of disallowing saving during certain game states, save yourself hours of work, just make the player wait 10 seconds until they're back to a "normal" game state to save.
On rawdata-serialization that assumes to be on the right pointer I tend to optionally add (controlled with a define-flag) a checksum where it makes sense e.g. each section or even struct/class-type and assert for this checksum as part of the deserialization-process. Obviously you would need to put info about using checksum or not in your file-header along file-version and such so you know if you need to read the checksum as well. My advice epecially for the load-process: use as much asserts as possible to check if the data you use to recreate your state makes still sense....
A very important point if you decide to have an auto-save only game, is to always save duplicates and a few previous saves. There's been some AA games that recently failed only because the saves had a chance to be corrupted with no way to recover even an older version.
From memory the S.T.A.L.K.E.R. games had some weirdness with quick loading. The maps seem to dump as much data as possible between saves. So it could have been raining when a save was made, then be sunny on a load. NPCs also seemed to get dumped and respawned on a load, barring, but not always, those close to the player (at the least NPCs forget what they were doing before the load). There's a setting many mods for that game make viewable that determines this distance, and it is possible that on a reload the player could find themselves with NPCs spawning on top of them, where before the area was empty. Just interesting seeing that a developer presumably was doing what they could to cull memory on loading, and what effect that could have on gameplay. That seems an extreme example, and something that with older games modders try and fix where possible with engine rewrites (as how saving works is a baked in feature) - so long as source code gets leaked, or with porting games to work in other engines like Unity.
Question for you Tim: what are your thoughts on NPC vendor currency limits? Do you prefer an infinite vendor cash system, allowing players a one-stop-shop to sell all their loot and not worry about bleeding the vendor dry or do you think giving vendors a finite currency bank is a better option? Some other system? I've played so many games where the simple act of selling all your loot becomes a time-consuming struggle since the choice was made to use NPC vendors with small, finite banks and/or the loot item cost vs. vendor bank scale was out of balance. From a player's perspective, aside from maybe immersion reasons, it seems like using an infinite system would help the player stay focused on gameplay rather than getting bogged down with UI/system management.
I like when the currency is limited but selling to certain shops gives more money depending on what the shop is selling. (Sell armor to the armory, sell potions to the alchemist, etc) That way if you just dump everything into one shop you’ll rarely hit the currency limit, since the items have lesser value. But this also requires clean city design so walking between shops doesn’t take up too much time. I also like when there’s regional price mark ups like in Kenshi. That way when you’re doing long haul trades it incentivizes hitting up multiple cities for trade. (Again map design can make this overly tedious though)
NetHack had pretty simple solution I rather liked: Have the store give the player store credit they can redeem in the future. Of course Nethack players instead used this to 'pre-pay' because they often got afflictions that would make them teleport randomly, and if you were in a shop and left without settling your tab, the cops came after you.
I believe it's a good idea to use some sort of serialization framework. Some can generate load/save functions from class and field annotations; saves a lot of time and avoids a lot of bugs. Some frameworks allow to choose save format at runtime - so you can say use text format for development build and binary for release.
This may be helpful for someone. I defined a save system using polymorphism (a coding concept), with a base class called SaveableObject. So whenever I'd trigger an event saveRequested, it would make all saveable objects serialize themselves with a custom logic, allowing to serialize cherrypicked data for each object, and then each savew object woul dbe savec as a single file. This allowed me to reset the state of an object by simply deleting it's save file and debug certain things in my game. When load, all saveable objects would deserialize their save file and load their previous state. Now, having a million files is cool for debugging, but it sucks when youér already in production, so what you can do is have yoru save manager (the one that triggers the events) have a list of all saveable objects in the scene, and once all save triggers are completed, have him compress all save files in a single file, and remove the .zip extension to something like.sav, .doom, .yourGameEdgyAbreviation
Hi Tim, I know you went a bit over this in your Fallout 2 video, but what your opinion on Fallout humor and do you think it was overdone in Fallout 2? Also, if you want to answer, how do you feel about the later games implementation of humor?
Huh! I've always hated when games won't let me save more or less whenever I want. Never realized there was actuall coding issues behin it. I'll be more tollerent of save points in the future =)
Hi Tim, It's me, some of everyone. Interesting topic. For my game, I don't like "save anywhere", I don't like "autosave". I like classic JRPG save points.. Which transport the character to a CRPG-style party camp, where they can save. For me, it's about being mindful about providing a good checkpoint to break up the content. Yet I notice most modern games are very much "autosave" or "save everywhere" type games. Which type of saving do you prefer in RPGs, and why?
Hi, everyone, it's me, everyone! :) One important thing to consider about "save anywhere" and autosave is respect to player's time. While discouraging save scumming is good, i wouldn't want to be forced to play additional hour just to get to a save spot. Or worse, having to grind a boss to be able to even start a journey to a save spot. An alternative would be keeping game paused for hours and days, which is ridiculous and should stay back in 8-16bit console era. I think best option would be "unlimited" save spot (like bed) + one autosave slot for bosses and one "save anywhere" slot that you can only load from main menu for when you have to quit the game. I really don't like it when games show every save you have. Like cyberpunk with its dozens of both manual saves and autosaves all piled together in one menu, named after the random quest you have active when you saved.
I think you can get away with any of the save systems as long as you have an exit save. If you go look at stardew valley, that is where a majority of their negative reviews stem from.
This made me think about the Quicksave option in Skyrim. There's a persistent theory that they can absolutely break your saves, not just on that particular save but the whole game. The theory goes that the Quicksave massively bloats the save system, presumably saving far too much information, and that once the game has got to that point its basically impossible to load without a hard crash. Ive never actually seen any evidence of it (but with modding its not that hard to crash your game) but because i'm superstitious i never, ever have one or make one. A large portion of the modding community is the same. I know the original wasn't the most stable to start with tbf.
I'm just going to point out that it's even harder than what you say. You didn't say anything about endianness and cross-platform saves. I mean, dumping an int in C is indeed fast and efficient, but it's also not cross-platform at all unless you think about the ordering of your bits. Some libraries offer binary and text save formats, which can be invaluable for debugging (stuff like protobuf and even C++ boost serialization if I remember well). However, saving pointers dumbly (like boost serialization did and maybe serde in Rust?) can easily lead to stack overflows, which means you may have to recompile your binary with larger stack space and hope. However, it would have been nice to speak a little bit about the design choices, not just the technical limitations around saving and loading. e.g. Why you would want to allow only save&quit, or why you don't want to allow save in combat. I know not being able to save in combat in Battle Brothers is a big plus for me because otherwise I could feel tempted to save and just savescum "bad luck" away, but that reason would vanish if the game didn't have any randomness (like chess).
While it's good to cater for endianness, you are extremely unlikely to encounter a Big Endian system in the wild these days. The last consumer product I know of that used Big-Endian were PowerPC based macs, and those were discontinued in 2006.
Have you ever played Kingdom Come: Deliverance? I know you don't review games but would be interesting to know if you had an opinion about that game's saving.
Topic of the moment! I was wanting your opinion of the Subnautica load/save mechanic which is one of the most bizarre I've ever encountered. You can't save scum and you are more or less in semi- permanent Iron Man mode. Basically if you die you lose everything you got since you last were in a base, and that stuff is also gone from the world. This in a game where resources never respawn. There is no Load/Restore capability at all. Which makes me struggle to understand why they even have a Save option at all. "Save" seems to mean "Don't lose my progress when I Quit" - surely that should be the sane default??!
Save & Load is complicated! I learned a LOT more about CODING by trying to tackle Save & Load concepts! :D I made a test project, before starting my first big Unity game, that was just about working out Save & Load with some Rigid Body sphere balls, and a simple Player and AI characters. I still haven't decided how to handle Save & Load in my game. I love Quicksave / Quickload (where the full game state is snapshot/restored), but I think I'll avoid that for my first Unity game! We'll see. :D
Hey, Tim. I assume you've skipped the asynchronous IO for writing the save state to the hard drive which enables the player to continue playing while the IO is active. I've seen it in PoE 1 vs PoE2. In PoE 1 the save was synchronous and as game progressed took more and more time to complete which led to a freeze in UX, while in PoE2 the save is asynchronous and the player can continue playing while the IO is busy.
That's not just async IO. That's the easy part. The hard part is taking an immutable snapshot of all the current game's state data while simultaneously allowing the game to continue to run and modify ITS copy of that state data.
@@gilgamechaI've been thinking of that while writing the original comment, however without seeing the exact implementation I wasn't sure to mention it as a particular challenge.
Neither should be hard if the data is well organized. And saving with a “file pointer” is a good start, but its very inefficient. The snapshop idea is the key, grab the state in a few milliseconds, then write it to disc directly or asyc if it’s really that big.
I would also add: "try to do it early"! I don't think a saving system is very fun to do. But it is easier if done early and to keep up with each new things you need to save/load. So you don't reach a point where you need to write the serialization function for hundreds of classes. It also helps a lot with testing to be able to load a save that will take you in the right conditions to test a bug/feature.
It's important to consider not just the technical and implementation decisions, but also the impact your save system has on gameplay just by itself. You don't always even *want* the player to be able to save anywhere. Having to make risky choices without the safety net of a quicksave ten seconds can raise the tension and avoid encouraging savescumming, especially if the the game has a death mechanic beyond just "reload an earlier save", such as Dark Souls, Shadows of Mordor's nemesis orcs, or roguelite games with metaprogression between runs. The original Ori had a mechanic where you could spend a resource to create a save point anywhere, so you could pick and choose where you thought was tricky enough to be worth being able to reload from, Shovel Knight allowed you to break checkpoints in levels for bonus rewards, the N64 Majora's Mask only allowed permanent saves when you reset the three-day cycle, making each new loop feel like you really are restarting from the beginning, almost like a new roguelite run in itself, and of course Getting Over It is entirely based around the game always saving *everything* - even your mistakes. One of the major problems I had with Breath of the Wild's durability system was the fact that death had almost no consequence, because you could always just reload to moments before it happened, and so there was little reason to use up rare and powerful items when you could just do it in 2-3 tries with common ones. In areas where your progress isn't saved, such as the Master Sword trials and Eventide Island, you're much more inclined to make use of every tool at your disposal to avoid having to start again, rather than trying to save them for later. A related decision is save slots - can the player make multiple branching saves, allowing them to go back potentially hours to redo an earlier decision, or just one persistent slot per new game? There are also decisions to make not just about saving, but loading as well. Most "serious" CRPGs always want to save and reload the exact moment the save was made, but that's not the only option. In many Zelda games, while you can save anywhere, you always reload the game at a fixed point, such as Link's house in Ocarina of Time, or at the entrance of the current area rather than the exact spot you were in, and in Hollow Knight, the game constantly autosaves, but loading the game always places the PC at the last checkpoint they rested at. This provides a compromise between being able to save anywhere, ensuring that the player is always free to stop playing and resume later without losing progress, while also only needing to serialize key long-term variables rather than the entire state of the world at that exact moment. Of course, it's then up to you as a designer to ensure this can't break other parts of progression, perhaps bypassing a puzzle that required to you escape a room (just save and quit out!) or breaking a key sequence by saving and resetting all of the NPCs involved to their default positions. Another example from Dark Souls - the game lets you save and quit to the menu at any point, and while it does save your *position*, it only stores whether each NPC on the map is dead or alive and not their current state or position, so savvy players can charge through a whole horde of enemies towards some treasure, then quickly save and reload to reset and deaggro every one.
in modern games loading should not be too demanding, so if you have a cutscene that is supposed to be covering up a load, some how save that the player has seen the cutscene, and allow them to skip when the load is completed. or if the cutscene is not covering up a load/transition then have the scene be skippable.
@Tim You didn't bring up games that continually save state which is fairly common in open world games particularly if they support multi-player. So instead of having a specific save file the world would maintain its state in its own file (or set of files) and each player would have its own file for state. Its a very different way to save but the most practical for some types of games. Also potentially different ways to optimize, like having various parts (world chunks & players) all save in parallel in different threads to spearate files. I'm currently building such a system for the first time and the parallelization makes me think I can get away with XML even though its slower than binary. Time will tell.
Wow, Tim, never knew such vast considerations and design was put into a game feature seemingly as taken for granted as saving and reloading a game anywhere. Thanks for imparting your knowledge! I was wondering how the quicksave system in Fallout (and Fallout 2) worked, as the game asks you to choose a save location where the quicksave will be assigned to, but if you move to another location (map) or pass some point during the game, the game doesn't seem to remember the original existing location and ask again to choose another location. Is this related to the limitations of the engine like you mentioned?
I took the easy way with my project, you can't save during combat and that cuts the effort in half instantly, I don't save anything related to AI because they would all be in Idle state, and they would be stationary or moving very slowly, so I could just store the location and rotation. (And health etc.)
I was making a game as a hobby a while back. First person horror game, simple I thought. Oh boy, why did i decide to add save game at the end of the development 😅. It delayed the project atleast 50%.
How do you make your creative decisions? Like, TOW could be different in millions of ways but it's very specific, do you have rules to choose one thing over another? One plot over another plot?
It is worth noting that until recently with super fast SSDs it was basically always faster to compress data and write that. The time saved on writes made up for the time spent on the compression, especially for verbose human readable things since they tend to compress well. I think now you'd have test. The downside is that the best compression means you can't really seek in the file. Modern systems have shifted a lot of these sorts of trade offs a fair bit with the changing performance characteristics of storage. These days it might be better to just allocate one big memory block that you don't expect save data to exceed, write to that then write it to disk in one go. You run the risk of bugs around handling data being larger than the buffer if that doesn't hapoen in testing, which it won't if you choose the buffer size right.
Hi Tim, Thank you, this is one I've been wondering about but I do have a bit more of a specific question about this. I get serialisation, and you will just store the players progress in a JSON. However what im wondering is how does npc positions get saved? If say Fallout 1 I get that, npc is in position x,y as they tend to always be there. But how does a full 3d game know that an NPC just happened to be walking behind a door on a random walk path, just before you saved? 3d games I still do not understand
I'm recalling that the Elder Scrolls: Oblivion and Fallout 3/ New Vegas had the issue where Quick Saving would over time lead to the game crashing more. Modders created an alternative that had players Hard Save instead when they prompted the game. ...As somehow Quick Saves were coded vs Hard Saving (pressing Escape and clicking save) that was causing the problem.
Save anywhere at anytime seems to not include saving during conversations. Probably for the best to make it more difficult to save scum dialog skill checks and when making difficult decisions though I'd guess it is usually not allowed for technical reasons.
Its safer to have the save-file slit into some meta-data and general progression data (like level, inventory, story state etc) in some more robust text format, and then the concrete serialized world data of all objects in a binary format. In case the save system breaks with a patch, there is at least the fallback option to reset to some town, and have the main player progression restorable. A other objects and NPCs reset to some default state.
Great video. Was really hoping for something on save editing. I'm fine with the speed of JSON for its convenience... but I don't want players editing the save to cheat. Do you just encrypt? Not sure what the best solution is. Thanks
If the save file is local, there is really no way to stop players from modifying it. You can only make it more inconvenient by saving raw data, or encrypting it (rather than using JSON or some other plain-text format). Note, even if it is encrypted, the game has to be able to encrypt and decrypt it, so the methods and keys are in your game code, which can be decompiled.
It occurs to me that a lot of these technical conveniences end up being QoL for players as well. Allowing saves during combat or physics events can easily cause a locked save. As a compulsive quick-saver I am quite glad if it doesn't work a second before death.
My favorite loading and saving state that is open world is Breath of the WIld's The Blood Moon rises which reset the world when the memory got to intense as far as I can speculate. So you could load in anywhere on the map but when the memory got too intense to crash the game, the blood moon rises cutscene would reset the memory so it doesn't have to remember the load state. I also liked Metroid Prime's loading system where you would have a bridge room that would do the loading and unloading of rooms. The problem with loading an open world is just that and I think BoTw solved the memory problem. But an unpopular opinion would be to have to pay for extra save slots or pay to autosave or quick save. People will hate it but as a publisher, I would push that on a studio to make more money. Jokes aside. At least, this will likely be stolen and then we will see these features done in games to increase revenue as pay to save becomes a thing. I would think that a basic flag system for what data is saved and what isn't like quests, etc and how many coins and items, etc that you have in your inventory and chests to be loaded in from a save. The save itself would be saving the flagged stuff and inventory and then it would reload at a point where you could easily test and run bugs. Autosave would simply save the game and then reload a fresh area when they reload. But if they want more than one save state, they will have to pay for each additional save state as well as maybe a monthly subscription to autosave. I am sorry if they steal this idea.
hi Tim, i am an inexperienced game designer who loves your RPGs and your channel has helped me a lot. thank you for being so generous with the knowledge you have gained over the years
Tim is definitely a generous teacher which is just another way to say he is a great teacher. Thanks Tim.
Here is a tip: implement load/save as early as possible. So you can figure it out as you go along + you don't have to stress about it + it will not be a huge task to do. (And the same is true for mod support for the game)
Second this and the same goes for networking. Retrofitting these is a huge headache.
Agree 100%. In fact I'm currently starting a new project and spent the last week building the I/O architecture and mechanics which includes loading game metadata, saving game state and mod support. Not fun to write but essential and something you want to get sorted out at the beginning.
you know its time to go to bed when you're still awake and tim uploaded
Lololol been there
unironically thats happened to me at least a couple time while Ive been up playing Temple
I think the most important thing is to implement saving and loading as early as possible in development. It makes testing everything so much easier if you can save a specific situation and load it later.
Here's a strange behaviour I found with the save system in the original Kings Quest III. I was save scumming my way up a mountain late in the game (you could very easily fall off the mountain trail and die). Save scumming was the only practical way of going up or down the mountains without magic. I had a single save game file and was using F5 and F7 to quickly load and save the game (IIRC they weren't quick save/load, but brought up the save/load interfaces). I walked off the mountain path and accidentally saved the game despite being dead. It was possible to save the game after you were dead. I had just discovered this the hard way. This was very frustrating to a quite young me. I never played that game again.
This experience taught me to always use multiple rolling saves so I always had something to go back to. These days I always create multiple saves and typically will run up against the maximum save game limit if the game has one.
A bit off-topic: I know people nowadays use the term "save scumming" all over, even in news publications, but it's actually the derogatory form of the original term, "save scrumming". The term comes from a sport called rugby, where they would do something called a "scrum" or "scrummage" which is basically a way for them to __restart a play__. But since there are a ton of people that aren't familiar with rugby, they auto-correct in their minds to something more familiar... like scum which doesn't make as much sense, unless you're insulting someone. However, as you mentioned, in the age of Kings Quest, Command and Conquer, etc, save scrumming was almost a must, especially if we were younger at the time.
@@KeiNovakNo, it's not. The term originated with players of roguelike games. Since roguelikes are built around permadeath, reloading a save to escape a mistake or reroll a random event is considered “scummy.”
Its funny how often there is no real reason to limit saves, the only game that had bloated over 100mb on some levels was crysis1(and i think it shwowed the size in the menu) and effectively your save limit was disk space
I immediately knew where this story was going once I read "I had a single save game file and was using F5 and F7 to quickly load and save the game".
We've all been there lmao
You got softlocked
You're seriously a treasure trove of knowledge and wisdom. I enjoy your content so much!
I'm in the same place, he's the man.
I just started to learn coding via Harvard's cs50 course online and I understood some of that! Int, string, double, float! How exciting!
Thanks, Tim!
Keep going!
CS50 is amazing!
Every video that you make Tim, is absolute gold! We need more people like you that share the ancient tribal knowledge.
This video reminded me how nice it is that Rust is both a performant systems language, and has an *extremely* straightforward serialization system in the form of the Serde library. In all cases I've used it, serializing a structure only requires you to annotate the struct as (de/)serializable, and the code generation does the rest. Serializing and deserializing is just one function call.
But also that serialization is only the starting point, and there's much more to this topic than just that.
Python and Java have similar systems. However, any change to the class can completely break it. I found it the hard way.
Serialization is the worst form of creating a save game you can chose of. It is easy to use and comfortable from a developers perspective. But it is not a good form of a players perspective.
Reason:
Every memory can have a bit flip. This leads to incorrect data being stored and the serialization technology is particularly susceptible to this. Such errors can accumulate. It is therefore better to store the data in a structured manner using non-serialized technology. This allows the data to be checked for plausibility and errors have less of an impact.
I once had a save game in Total War : ROME that was created via serialization. This save game was a late save game in the game and it always caused the game to crash on the next round.
@@OpenGL4ever Surely you could add error checking to the serialized version too? I've kinda thought that modern filesystems would deal with single bits being flipped, but evidently not. Still, I'd rather come up with a proper system that can recover from errors in the final serialized data. That honestly seems more robust and easier to me than fixing the issues in random save/load functions.
Such a great video (and channel). There aren't enough tutorials around that go through the important high-level game design problems in detail like this. I definitely feel like getting clear on what your problem is is halfway to solving it - whoever originally said that.
Yea I really wish we had more channels like this.
I really appreciate this channel and your pov. Even if im not pursuing game dev
This has been a thorn in my side for all of the projects I have worked on so far. Glad that it’s not just me haha
As a kid who had a daily half-hour time limit for video games, games that could save anytime anywhere blew my mind.
Thanks for the video, Tim. It came at just the right time! I've been troubled by file I/O and my save game system for months, and took a break to focus on other things.
This video has given me the motivation to dive back into it.
Oh my god this is so helpful. For the past month I'm learning how to do serialization for my unity project, and the moment I hear serialization my heart rate immediately went up :(
This has been one of those things I thought I would understand, but quickly was humbled by. Thank you so much for this video!
I don’t know how big of a feature it is, but I appreciate when RPG separate saves per-run, with manual saves, quick saves and auto saves being kept separate.
Sir i want to Thank you the way you explane the stuff. so everybody is able to understand, all so like you take your to explane. am lovin it. Thank you.
This is why I favor passwords. Especially for games like Scrabble.
For loading I usually just read and parse the whole data from disk once and feed it into the load method for each class, and each class is responsible for picking the parts of the data that it cares about, so the method signature of all the load methods are basically the same.
I like JSON (or whatever human readable format) as it makes it easier for people to go in and play around with the data, easier to debug/easier to get good bug reports as a tester can go in and look if some field has a bad value saved somehow, allows testers to modify their save manually to get themselves into a particular state they want to test (if you don't want to bother creating specific tools for that kind of thing), and it generally makes modding a lot easier.
It also provides better protection against a broken save due to a bit flip in memory. The data can not only be checked for plausibility during parsing, but can also be repaired at any time by the user. This type of savegame storage is therefore clearly preferable to serialization.
I find saving and loading to be one of the most challenging parts of my game dev process.
I loved the idea I saw in one of the later Tomb Raider games actually, I think it was Tomb Raider 3. Where you'd collect crystals that you could use to save your game anywhere aside from cutscene/checkpoint saves. It initially felt more restrictive than Tomb Raider 2's save anywhere mechanic, but it actually made saving feel important and like an in-game resource which then gave it a feeling of a meta-game as well.
Thanks for explaining the high level decisions you need to make for specific implementations with some examples. You explanation on how classes would implement save file IO is pretty much exactly how I was taught it.
😮You are bringing the hell talking about this matter
I sincerely, deeply appreciate you, Tim.
I never even thought about things like this thanks this was very insightful and I had no idea I needed to learn about serialization to know where to start with saving and loading
Getting into some of the technical stuff is really helpful. Thanks for your insight
I could listen to you all day this is good stuff even if its obvious
some specific things/cases I've never thought about
Hey Tim. Hope you're having a great day!
This is a great topic. In my own game, I severely underestimated the work needed to code such a system.
Having worked in tech the last couple of millennia, I went the JSON route. It works really well at my early stage of development because when a test has had an issue on their machine, they can send me the file, and it's fairly easy to figure out what's gone wrong. The file size on my modest metroidvania is 30k, which isn't great (and i could probably get down by compressing), but save and load is actually still very fast. I save the game when you exit to the title screen, and I would say it's instantaneous, so if you're not writing out many megabytes of data, it will probably serve a lot of people's needs. Even better in c#, you get serialization basically for free so you just dump everything to a string and read write that (which has memory implications, but may be fine in a lot of applications). C# constructs my json into a series of structs, that each module knows how to hydrate into game state. It's really easy, flexible, trivial to add a subsystem, and human readable at the cost of memory and some efficiency which honestly you could even optimize out with a more efficient file writer if you really needed to, so would recommend.
JSON isn't the best (there are a few binary equivalent formats that would produce faster and smaller results while keeping the main benefits), but a save file that isn't 'fragile' is more important than maximum speed or space efficiency. If it comes down to it, you could always compress the result when you save it anyway.
@@GrandHighGamer Reading JSON is actually fairly optimised in .NET in terms of both speed and memory.
It does come with certain assumptions, namely, its implementation is one of a depth-first and a single-pass forward-only reader.
So even megabytes and megabytes of game state only need a few kilobytes at the JSON layer.
you got to save before you load, know when to hold em, and know when to quicksave
.. know when to walk away, know when to Ctrl Alt Tab...
@@gilgamecha And when the game intercepts Alt-F4 and it tells you "Hey friend, you didn't mean to do that." Then, it loops you back into the game.
You never counttttt yourrrrr pixels, when youre settingggg resssolution @@gilgamecha
I love when I can save a lot, not anytime anywhere, but at least before big battles and anytime when you are idle, on map etc. and I like quicksaves too, for instance in First Person RPGs. Not a big fan of checkpoints, but depends on game. For example Crash Bandicoot did it well.
Edit: I used to be a fan of password saves which generated a code based on your statistics as well as level progress.
Kind of the same for me, though checkpoints can have a massive benefit.
I remember at least two good examples for that:
Alien vs predator 1, I remember running through corridors after hardly defeating a very hard enemy. With aliens on my heel. Shooting at every movement, panicking because I knew if I died I had to do all the fight again. It increased the stakes by a lot, compared to the typical save, die, reload...
Similar experience was in Operation flashpoint. Dashing over a meadow to avoid a tank. Heart pumping, hearing the damn thing shot, explosion nearby, ducking running uphill into the cover of the trees, another close explosion. Then some shots, more running, sweating like I was running myself. Feeling more save after getting some more distance between me and the tank.. and then stumbling over a speznaz lying in a bush, reflex shooting, ducking, hiding...
It's very hard to reproduce that with save/load everywhere... But also if you have to repeat that the 6th time because bad luck or, even worse, a have crash, then you start hating it again :D
@@Glimmlampe1982 That's why i didn't like Alien vs. Predator 1. They fixed this issue in Alien vs. Predator 2. It's no fun if you have to replay a level scene over and over again because you die before you finish each time. It's true that it increases the thrill, but the downside is more serious. So it is a big no no.
Versioning.
IMHO, versioning your stored data is super important so that when you read data, you can verify that it's a version which you understand, and if it's an older version invoke different load-state code than for the latest version.
Especially when writing out data serialized to a stream, based on my experience I think it's very important that each class/module that has its own custom write/read object code writes out a version number as very first thing for future use while reading back the data.
Better to ignore a version number when you don't need it, then to need it and not have it!
For data stored in a textual version this is also important but for raw data serialization it's even more important because often the stream will otherwise not contain any tags / markers to indicate what each value means, which field it maps to, and perhaps not even what type it is and how many bytes in size!
(Of course if you use something like Protobuf for data serialization then the Protobuf framework takes on at least part of the responsibility of versioning your data and tagging the fields, types, and data sizes).
Keeping a couple of autosave or quicksave slots too, that way one 'bad save' is potentially recoverable. In a way that's kind of the point of autosaves (within the RPG genre the video seems to focus on). If the player forgets to save or the game suddenly crashes, they're not out an hour of progress.
Great advice!
Always a new angle to consider. Thank you, sir!
Hey there! Great video as always! I have to say though: I disagree that text data is easier to handle compare to binary. If anything, I think it's the opposite: whether you convert your data to JSON or binary, you STILL have to serialize stuff, that hasn't changed. Now when you read the data, if you went for text, it means you have to parse it. It isn't just slower, it's also more difficult. If I'm loading a binary data, I just have to read bytes, and assuming I know the order my fields appear in, that's fairly easy to do. All of a sudden if you've got text you have to parse EVERYTHING, and in fact you don't even know how long your data is going to be, so you can't rely on fixed offsets to switch from a section to another.
There's nothing text can do that binary can't, they both involve serialization and deserialization of some kind, but what it comes down to is: do you really need your data yo be human readable?
Thanks for this overview, especially considering the depth of your experience. This is a topic that the theory seems simple on the surface, but still made my head spin when I thought of the details and what-ifs. I did get a little lost when you were talking about pointers but I figured it was a C++ thing. Thanks again.
Once, I was working on a game where we implemented an auto-save feature on a background timer. Prior to that, we only had a quit-save, during which we deliberately broke AI, knowing that it would restore to mostly-the-same state on load. We ended up with some really weird AI behavior bugs, with the auto save regularly breaking the AI mid game. Most of these bugs surfaced long after we made the auto save update, making it a pretty hard bug to get to the root of.
Now I know why I've put off save/load as a new Unity designer. My intuition was right. I'm almost ashamed that, when I was just a "gamer," my thinking was just "Yeah push F5, and it saves the game!" Thank you. This was one of the best.
Organization: I like a "player profile" option, to separate saves into character specific "folders". Its easier to abandon/pausing a character and switch to a new one, without getting a big messy list of old saves. Or if two people play on the same machine. And for a save slot, next to a screenshot, also showing some general state like level, location, maybe current active quest name.
Hi, Tim. It's us, everyone !
And me😊
This comment is amazing.
@@Seanhmattsonit’s a bit overpunctuated but if I’m commenting shortly after upload you can bet imma say “Hi Tim, it’s us, everyone” or a similar variation 😊
You covered pretty much all of save/loading. I've never used saving raw memory using pointers myself though. But that does sound clever.
The project I'm on now uses JSON with file versioning, so the loader knows what mods were installed at the time of save.
Wow.
All the time during the video I was thinking about Bethesda games.
Is it really possible to keep track of the precise position and orientation of every single interactable in-game-object present in each and every map of Skyrim, and still manage to have a usable save-load system both in terms of speed and file size?
I mean, no wonder my Xbox360 couldn't manage it, back then, after one or two hundreds hours of world disarraying gameplay from my part!
Thanks for your videos!
That is indeed impressive.
Their games are some of the few I had to purposely limit my saves for. Now it's become a habit to rotate through a handful of saves, even if they offer "unlimited" slots.
Bethesda games let you load the base game, and then layer 254 ESM/ESP formatted addons/mods on top.
You might notice this is 1 short of 256: this is because mod slot FF is actually where Bethesda games store all mutated game state.
Which is to say, a savegame in Skyrim is literally a mod that mutates the game state from default to whatever you've done and accomplished in game.
Has many bugs, but IMO it's quite a clever approach.
@@billy65bob
Yes, I guessed the save system for in-game-objects location and orientation had to be based on delta values of some sort vs the default initial state of the game world.
At least that way the amount of data related to that aspect of the game world state, at any save, wouldn't reach its theoretical maximum until you've moved every single object you can move.
I had no idea that, in order to implement such an approach,
those games could use the same systems as mods, though:
thanks for the info!
I know you said before you don't care about save-scumming, but as a player I was sometimes grateful to the designer when that choice was taken away from me. It's all too easy to optimize the fun out of your game when you press F5 every 10 seconds and reload after every setback. Of course I could just "not do it", but that's not how my brain is wired.
In my game I have decided to lock the randomization in place before saving, so that save-scumming doesn't get you anything different. Some players hate it, some don't care, but there's no pleasing everyone I guess.
Tim, thank you so much for every video you put out!
I cannot look at his T-shirt without hearing the Spacer's Choice jingle in my head. Damn you, Tim Cain!!!
It's not the best jingle it's Spacer's jingle!
Thank you this was thought provoking!
I've worked on games that use fixed order save/load serializers and your description still made me really think. Hearing you describe them in this way made me think we should have written all the data into some hierarchical dynamic data structure in memory and then serialized that thing sequentially. Kind of like the memento pattern. You could add CRC checking to the end of each module entry which would hopefully make serialization issues more apparent. Also the actual file manipulation should be quite fast since you can blast through the whole map writing binary data.
leave it to Tim to have a video on my feed right as I open youtube and it's an insightful take on something I literally never thought of
In Eschalon the save anywhere feature allowed for an exploit to save after damaging an enemy but right before relinquishing your "turn", so basically you could do infinite damage by savescumming
This is a very informative video. Greatly appreciated 👏
I'm currently starting a new project and spent the last week building the I/O architecture and mechanics which includes loading game metadata, saving game state and mod support.
My current plan is to save game state using XML because its human readable, easy to debug, easy to edit and easier to version. Also game metadata (plus mod data) will be in XML so same I/O system can be used to read configuration. Haven't benchmarked XML in a long time so not sure if it will end up being performant. Which is why I built an entirely custom I/O architecture that provides the class load/save methods with a reader/writer interface plus a generic storage parameter. For XML the storage is an XML Element but I can write alternative readers & writers that in theory could be anything including a file pointer.
Writing this kind of code isn't fun but is essential and something you want to get sorted out at the very beginning. If you try and implement or change this system later its a lot more work as you have to go through a modify A LOT of existing code.
Hey Tim, I was wondering what your thoughts were on the increase in game industry layoffs lately. What does this mean for the future of games? What would you say to someone who wants to get into the industry? EA recently talked about incorporating generative AI right after firing hundreds of employees. I am worried game companies are looking for more and more ways to outsource and reduce employees in an already competitive industry. What are your thoughts on game unions? Thanks for all of the great videos!
I am working on a couple of videos, on both terrible things that happening in the game industry as well as changes that are happening (and yeah, there is overlap there). Keep in mind my perspective on things is very long term, and I have heard "doom and gloom" prophecies for literally DECADES...things like "consoles are dead", "PC gaming is dead", "turn based combat is dead", "RPGs are dead", "single player games are dead", "all artists are being replaced by 3D scanning and modeling", etc. So I breaking things into two videos...just how bad are things really...and people need to expect and adapt to change, because it is NOT going to stop.
Expect them in a few weeks.
@@CainOnGames looking forward to it! I think the future of gaming is going to be exciting.
I'd be really interested in hearing more about save systems from a design point of view.
I'm designing a game currently that I want to be dark and serious, and one where the player seriously considers their options due to consequence. However, I'm worried a game with no custom saves, and only auto-saves might not be fun at all to play.
What do you see as the pros and cons to letting the player save when they want to. In other words is save-scumming something to worry about, or just let be?
I'm actually implementing Saving/Loading right now. For me, the extensive work is in the UI, as I made the decision to have "save rooms" like Castlevania: Symphony of the Night since my game is a open-world action JRPG with the same view point.
And I love JSON.
I usually prefer save anywhere systems when I play games but checkpoints aren't always bad if they are not too far appart. They help with my obsession with saving every 5 minutes. What I absolutely hate is saving systems where you have to spend a resource to save. Luckily not many like that around.
Save slots were used especially in the past, when storage space was still tight and DOS limited you to 8 characters for the file name and 3 for its extension. The save slot allowed the player to assign a longer name internally and usually also showed the date if it was done correctly. At the file system level, everything was saved in the same folder as the program data. You then had a file for each of the available slots.
Nowadays, of course, none of this is necessary anymore and slotless savegames are much better.
Hi, Tim! You were talking about the technical aspect of loading and saving, I would love to hear your thoughts on the gameplay impact of different types of loading and saving.
The migration of files from a version to the next is always fun. Setting up a reeeeallly good testing suite is mandatory. Otherwise, the kind of esoteric bugs it can cause will drive you insane
I remember in both Fallout 1 and Fallout 2 when they were major patches early on that the patches broke the save games and I had to start over again
7:35 games that let me name my saves are the best. I have so much fun describing what I was doing in excruciating detail.
for some reason I was expecting a video on Save scumming :D anyway, I personally found that Entity Component Systems are pretty handy when you need to serialize a state because they tend to stay very orderly and easy to read and write, as long as you don't use too many third party libraries that keep an internal states, like many AI libraries.
Much as I hate Bethesda, I think it's kind of cool that Save Games for Bethesda's games are literally just a mod.
It's mod 255 (or FF) to be exact, if you ever wondered why you're restricted to 254 addons/mods of the ESP/ESM format.
10:40 The easy solution I used for this, was to put a EOF check inside every single loop or read of variable length (i.e. strings) - It's pretty obvious you messed up when the loop wants to read 1787571723 items (and EOFs) instead of say a more reasonable number like 206.
Even if it doesn't bug out at the exact spot, it usually blows up close enough to the problem that I can quickly find the mismatched spot and fix it.
That said, I don't think binary formats are very much in vogue anymore; quite likely that games these days would just serialise either a JSON file or a series of them, and then shove them into a compressed container if you're lucky. Which avoids the biggest problem with binary formats: inter-version compatibility.
That was very interesting. I always wanted to hear about save/load from a developer. I wish you also made comments on how you deal with encryption or whatever else you use to protect save games against tampering when saving on local disk. Also, some comments on cloud saves / sync would be interesting.
In my opinion it is totally unnecessary for a single player game. If they can HexEd binary data let them have fun with it
Useless complexity for offline games where hacks/mods arent a problem. If youre going for online leaderbaords, I've seen a indie dev periodically check and ban records that arent posted on the speedrun site.
Hey Tim! Question of the day: If you had to choose now, would you rather...
Work on a game that becomes an instant cult classic and marks a generation but puts your studio at the edge of bankrupcy?
Or...
Make a basic bitch RPG that sells millions and your soul?
1:04 just a note here: be aware that some low level language specific serialisation libraries don't promise to be compatible between versions.
Off the top of my head though, I only remember gob in golang suffering from this. I don't remember if pickle in python is more stable or not.
What I didn't realize when I started developing my game is that there's no point in development where you can "relax" about saving, it's constant consideration about what needs to be saved and how to save it. You might think your save system works well until you realize "Wait, can I actually save when X feature is active?" and often you realize the answer is "no" and you have to refactor stuff so it can. That's why I prefer the approach of disallowing saving during certain game states, save yourself hours of work, just make the player wait 10 seconds until they're back to a "normal" game state to save.
On rawdata-serialization that assumes to be on the right pointer I tend to optionally add (controlled with a define-flag) a checksum where it makes sense e.g. each section or even struct/class-type and assert for this checksum as part of the deserialization-process. Obviously you would need to put info about using checksum or not in your file-header along file-version and such so you know if you need to read the checksum as well.
My advice epecially for the load-process: use as much asserts as possible to check if the data you use to recreate your state makes still sense....
A very important point if you decide to have an auto-save only game, is to always save duplicates and a few previous saves. There's been some AA games that recently failed only because the saves had a chance to be corrupted with no way to recover even an older version.
From memory the S.T.A.L.K.E.R. games had some weirdness with quick loading. The maps seem to dump as much data as possible between saves. So it could have been raining when a save was made, then be sunny on a load. NPCs also seemed to get dumped and respawned on a load, barring, but not always, those close to the player (at the least NPCs forget what they were doing before the load). There's a setting many mods for that game make viewable that determines this distance, and it is possible that on a reload the player could find themselves with NPCs spawning on top of them, where before the area was empty.
Just interesting seeing that a developer presumably was doing what they could to cull memory on loading, and what effect that could have on gameplay. That seems an extreme example, and something that with older games modders try and fix where possible with engine rewrites (as how saving works is a baked in feature) - so long as source code gets leaked, or with porting games to work in other engines like Unity.
Question for you Tim: what are your thoughts on NPC vendor currency limits? Do you prefer an infinite vendor cash system, allowing players a one-stop-shop to sell all their loot and not worry about bleeding the vendor dry or do you think giving vendors a finite currency bank is a better option? Some other system?
I've played so many games where the simple act of selling all your loot becomes a time-consuming struggle since the choice was made to use NPC vendors with small, finite banks and/or the loot item cost vs. vendor bank scale was out of balance. From a player's perspective, aside from maybe immersion reasons, it seems like using an infinite system would help the player stay focused on gameplay rather than getting bogged down with UI/system management.
I like when the currency is limited but selling to certain shops gives more money depending on what the shop is selling.
(Sell armor to the armory, sell potions to the alchemist, etc)
That way if you just dump everything into one shop you’ll rarely hit the currency limit, since the items have lesser value.
But this also requires clean city design so walking between shops doesn’t take up too much time.
I also like when there’s regional price mark ups like in Kenshi. That way when you’re doing long haul trades it incentivizes hitting up multiple cities for trade.
(Again map design can make this overly tedious though)
NetHack had pretty simple solution I rather liked: Have the store give the player store credit they can redeem in the future.
Of course Nethack players instead used this to 'pre-pay' because they often got afflictions that would make them teleport randomly, and if you were in a shop and left without settling your tab, the cops came after you.
I believe it's a good idea to use some sort of serialization framework. Some can generate load/save functions from class and field annotations; saves a lot of time and avoids a lot of bugs. Some frameworks allow to choose save format at runtime - so you can say use text format for development build and binary for release.
I was going to ask this as well, thanks for the video 👍
This may be helpful for someone. I defined a save system using polymorphism (a coding concept), with a base class called SaveableObject. So whenever I'd trigger an event saveRequested, it would make all saveable objects serialize themselves with a custom logic, allowing to serialize cherrypicked data for each object, and then each savew object woul dbe savec as a single file. This allowed me to reset the state of an object by simply deleting it's save file and debug certain things in my game. When load, all saveable objects would deserialize their save file and load their previous state. Now, having a million files is cool for debugging, but it sucks when youér already in production, so what you can do is have yoru save manager (the one that triggers the events) have a list of all saveable objects in the scene, and once all save triggers are completed, have him compress all save files in a single file, and remove the .zip extension to something like.sav, .doom, .yourGameEdgyAbreviation
I don't remember what game traumatized me but I have a superstition that I shouldn't save when my character is moving in an elevator 🙂
Probably Fallout 4 where elevators are often secret load screens.
Hi Tim,
I know you went a bit over this in your Fallout 2 video, but what your opinion on Fallout humor and do you think it was overdone in Fallout 2? Also, if you want to answer, how do you feel about the later games implementation of humor?
Did you see my video on humor in games in general?
ruclips.net/video/3mfl_jOf-Jw/видео.html
@@CainOnGames No, I haven't will watch it when I get the chance, thanks.
Huh! I've always hated when games won't let me save more or less whenever I want. Never realized there was actuall coding issues behin it. I'll be more tollerent of save points in the future =)
Hi Tim, It's me, some of everyone. Interesting topic. For my game, I don't like "save anywhere", I don't like "autosave". I like classic JRPG save points.. Which transport the character to a CRPG-style party camp, where they can save. For me, it's about being mindful about providing a good checkpoint to break up the content. Yet I notice most modern games are very much "autosave" or "save everywhere" type games. Which type of saving do you prefer in RPGs, and why?
Hi, everyone, it's me, everyone! :)
One important thing to consider about "save anywhere" and autosave is respect to player's time.
While discouraging save scumming is good, i wouldn't want to be forced to play additional hour just to get to a save spot. Or worse, having to grind a boss to be able to even start a journey to a save spot. An alternative would be keeping game paused for hours and days, which is ridiculous and should stay back in 8-16bit console era.
I think best option would be "unlimited" save spot (like bed) + one autosave slot for bosses and one "save anywhere" slot that you can only load from main menu for when you have to quit the game.
I really don't like it when games show every save you have. Like cyberpunk with its dozens of both manual saves and autosaves all piled together in one menu, named after the random quest you have active when you saved.
I think you can get away with any of the save systems as long as you have an exit save. If you go look at stardew valley, that is where a majority of their negative reviews stem from.
This made me think about the Quicksave option in Skyrim. There's a persistent theory that they can absolutely break your saves, not just on that particular save but the whole game. The theory goes that the Quicksave massively bloats the save system, presumably saving far too much information, and that once the game has got to that point its basically impossible to load without a hard crash. Ive never actually seen any evidence of it (but with modding its not that hard to crash your game) but because i'm superstitious i never, ever have one or make one. A large portion of the modding community is the same. I know the original wasn't the most stable to start with tbf.
I'm just going to point out that it's even harder than what you say.
You didn't say anything about endianness and cross-platform saves.
I mean, dumping an int in C is indeed fast and efficient, but it's also not cross-platform at all unless you think about the ordering of your bits.
Some libraries offer binary and text save formats, which can be invaluable for debugging (stuff like protobuf and even C++ boost serialization if I remember well). However, saving pointers dumbly (like boost serialization did and maybe serde in Rust?) can easily lead to stack overflows, which means you may have to recompile your binary with larger stack space and hope.
However, it would have been nice to speak a little bit about the design choices, not just the technical limitations around saving and loading.
e.g. Why you would want to allow only save&quit, or why you don't want to allow save in combat. I know not being able to save in combat in Battle Brothers is a big plus for me because otherwise I could feel tempted to save and just savescum "bad luck" away, but that reason would vanish if the game didn't have any randomness (like chess).
While it's good to cater for endianness, you are extremely unlikely to encounter a Big Endian system in the wild these days.
The last consumer product I know of that used Big-Endian were PowerPC based macs, and those were discontinued in 2006.
Tim I’d love your thoughts on the trailer for the fallout show
Have you ever played Kingdom Come: Deliverance? I know you don't review games but would be interesting to know if you had an opinion about that game's saving.
Topic of the moment! I was wanting your opinion of the Subnautica load/save mechanic which is one of the most bizarre I've ever encountered. You can't save scum and you are more or less in semi- permanent Iron Man mode. Basically if you die you lose everything you got since you last were in a base, and that stuff is also gone from the world. This in a game where resources never respawn. There is no Load/Restore capability at all. Which makes me struggle to understand why they even have a Save option at all. "Save" seems to mean "Don't lose my progress when I Quit" - surely that should be the sane default??!
Save & Load is complicated! I learned a LOT more about CODING by trying to tackle Save & Load concepts! :D
I made a test project, before starting my first big Unity game, that was just about working out Save & Load with some Rigid Body sphere balls, and a simple Player and AI characters.
I still haven't decided how to handle Save & Load in my game. I love Quicksave / Quickload (where the full game state is snapshot/restored), but I think I'll avoid that for my first Unity game!
We'll see. :D
Hey, Tim. I assume you've skipped the asynchronous IO for writing the save state to the hard drive which enables the player to continue playing while the IO is active. I've seen it in PoE 1 vs PoE2. In PoE 1 the save was synchronous and as game progressed took more and more time to complete which led to a freeze in UX, while in PoE2 the save is asynchronous and the player can continue playing while the IO is busy.
That's not just async IO. That's the easy part. The hard part is taking an immutable snapshot of all the current game's state data while simultaneously allowing the game to continue to run and modify ITS copy of that state data.
@@gilgamechaI've been thinking of that while writing the original comment, however without seeing the exact implementation I wasn't sure to mention it as a particular challenge.
@@gilgamechaThat.
Neither should be hard if the data is well organized. And saving with a “file pointer” is a good start, but its very inefficient. The snapshop idea is the key, grab the state in a few milliseconds, then write it to disc directly or asyc if it’s really that big.
I would also add: "try to do it early"! I don't think a saving system is very fun to do. But it is easier if done early and to keep up with each new things you need to save/load. So you don't reach a point where you need to write the serialization function for hundreds of classes. It also helps a lot with testing to be able to load a save that will take you in the right conditions to test a bug/feature.
It's important to consider not just the technical and implementation decisions, but also the impact your save system has on gameplay just by itself. You don't always even *want* the player to be able to save anywhere. Having to make risky choices without the safety net of a quicksave ten seconds can raise the tension and avoid encouraging savescumming, especially if the the game has a death mechanic beyond just "reload an earlier save", such as Dark Souls, Shadows of Mordor's nemesis orcs, or roguelite games with metaprogression between runs. The original Ori had a mechanic where you could spend a resource to create a save point anywhere, so you could pick and choose where you thought was tricky enough to be worth being able to reload from, Shovel Knight allowed you to break checkpoints in levels for bonus rewards, the N64 Majora's Mask only allowed permanent saves when you reset the three-day cycle, making each new loop feel like you really are restarting from the beginning, almost like a new roguelite run in itself, and of course Getting Over It is entirely based around the game always saving *everything* - even your mistakes. One of the major problems I had with Breath of the Wild's durability system was the fact that death had almost no consequence, because you could always just reload to moments before it happened, and so there was little reason to use up rare and powerful items when you could just do it in 2-3 tries with common ones. In areas where your progress isn't saved, such as the Master Sword trials and Eventide Island, you're much more inclined to make use of every tool at your disposal to avoid having to start again, rather than trying to save them for later. A related decision is save slots - can the player make multiple branching saves, allowing them to go back potentially hours to redo an earlier decision, or just one persistent slot per new game?
There are also decisions to make not just about saving, but loading as well. Most "serious" CRPGs always want to save and reload the exact moment the save was made, but that's not the only option. In many Zelda games, while you can save anywhere, you always reload the game at a fixed point, such as Link's house in Ocarina of Time, or at the entrance of the current area rather than the exact spot you were in, and in Hollow Knight, the game constantly autosaves, but loading the game always places the PC at the last checkpoint they rested at.
This provides a compromise between being able to save anywhere, ensuring that the player is always free to stop playing and resume later without losing progress, while also only needing to serialize key long-term variables rather than the entire state of the world at that exact moment. Of course, it's then up to you as a designer to ensure this can't break other parts of progression, perhaps bypassing a puzzle that required to you escape a room (just save and quit out!) or breaking a key sequence by saving and resetting all of the NPCs involved to their default positions. Another example from Dark Souls - the game lets you save and quit to the menu at any point, and while it does save your *position*, it only stores whether each NPC on the map is dead or alive and not their current state or position, so savvy players can charge through a whole horde of enemies towards some treasure, then quickly save and reload to reset and deaggro every one.
in modern games loading should not be too demanding, so if you have a cutscene that is supposed to be covering up a load, some how save that the player has seen the cutscene, and allow them to skip when the load is completed.
or if the cutscene is not covering up a load/transition then have the scene be skippable.
@Tim You didn't bring up games that continually save state which is fairly common in open world games particularly if they support multi-player. So instead of having a specific save file the world would maintain its state in its own file (or set of files) and each player would have its own file for state. Its a very different way to save but the most practical for some types of games.
Also potentially different ways to optimize, like having various parts (world chunks & players) all save in parallel in different threads to spearate files. I'm currently building such a system for the first time and the parallelization makes me think I can get away with XML even though its slower than binary. Time will tell.
Wow, Tim, never knew such vast considerations and design was put into a game feature seemingly as taken for granted as saving and reloading a game anywhere. Thanks for imparting your knowledge!
I was wondering how the quicksave system in Fallout (and Fallout 2) worked, as the game asks you to choose a save location where the quicksave will be assigned to, but if you move to another location (map) or pass some point during the game, the game doesn't seem to remember the original existing location and ask again to choose another location. Is this related to the limitations of the engine like you mentioned?
I took the easy way with my project, you can't save during combat and that cuts the effort in half instantly, I don't save anything related to AI because they would all be in Idle state, and they would be stationary or moving very slowly, so I could just store the location and rotation. (And health etc.)
I was making a game as a hobby a while back. First person horror game, simple I thought.
Oh boy, why did i decide to add save game at the end of the development 😅. It delayed the project atleast 50%.
How do you make your creative decisions? Like, TOW could be different in millions of ways but it's very specific, do you have rules to choose one thing over another? One plot over another plot?
It is worth noting that until recently with super fast SSDs it was basically always faster to compress data and write that. The time saved on writes made up for the time spent on the compression, especially for verbose human readable things since they tend to compress well.
I think now you'd have test. The downside is that the best compression means you can't really seek in the file.
Modern systems have shifted a lot of these sorts of trade offs a fair bit with the changing performance characteristics of storage. These days it might be better to just allocate one big memory block that you don't expect save data to exceed, write to that then write it to disk in one go. You run the risk of bugs around handling data being larger than the buffer if that doesn't hapoen in testing, which it won't if you choose the buffer size right.
Hi Tim,
Thank you, this is one I've been wondering about but I do have a bit more of a specific question about this. I get serialisation, and you will just store the players progress in a JSON. However what im wondering is how does npc positions get saved?
If say Fallout 1 I get that, npc is in position x,y as they tend to always be there. But how does a full 3d game know that an NPC just happened to be walking behind a door on a random walk path, just before you saved?
3d games I still do not understand
I'm recalling that the Elder Scrolls: Oblivion and Fallout 3/ New Vegas had the issue where Quick Saving would over time lead to the game crashing more. Modders created an alternative that had players Hard Save instead when they prompted the game. ...As somehow Quick Saves were coded vs Hard Saving (pressing Escape and clicking save) that was causing the problem.
Save anywhere at anytime seems to not include saving during conversations. Probably for the best to make it more difficult to save scum dialog skill checks and when making difficult decisions though I'd guess it is usually not allowed for technical reasons.
Hey Tim, i was wondering if you haven't already done a video on it, what are your thoughts on the souls type games?
Its safer to have the save-file slit into some meta-data and general progression data (like level, inventory, story state etc) in some more robust text format, and then the concrete serialized world data of all objects in a binary format. In case the save system breaks with a patch, there is at least the fallback option to reset to some town, and have the main player progression restorable. A other objects and NPCs reset to some default state.
Great video. Was really hoping for something on save editing. I'm fine with the speed of JSON for its convenience... but I don't want players editing the save to cheat. Do you just encrypt? Not sure what the best solution is. Thanks
If the save file is local, there is really no way to stop players from modifying it. You can only make it more inconvenient by saving raw data, or encrypting it (rather than using JSON or some other plain-text format). Note, even if it is encrypted, the game has to be able to encrypt and decrypt it, so the methods and keys are in your game code, which can be decompiled.
I have reached a state where without audio and just subtitles I can hear Tim speak
It occurs to me that a lot of these technical conveniences end up being QoL for players as well. Allowing saves during combat or physics events can easily cause a locked save. As a compulsive quick-saver I am quite glad if it doesn't work a second before death.
My favorite loading and saving state that is open world is Breath of the WIld's The Blood Moon rises which reset the world when the memory got to intense as far as I can speculate. So you could load in anywhere on the map but when the memory got too intense to crash the game, the blood moon rises cutscene would reset the memory so it doesn't have to remember the load state. I also liked Metroid Prime's loading system where you would have a bridge room that would do the loading and unloading of rooms. The problem with loading an open world is just that and I think BoTw solved the memory problem. But an unpopular opinion would be to have to pay for extra save slots or pay to autosave or quick save. People will hate it but as a publisher, I would push that on a studio to make more money. Jokes aside. At least, this will likely be stolen and then we will see these features done in games to increase revenue as pay to save becomes a thing. I would think that a basic flag system for what data is saved and what isn't like quests, etc and how many coins and items, etc that you have in your inventory and chests to be loaded in from a save. The save itself would be saving the flagged stuff and inventory and then it would reload at a point where you could easily test and run bugs. Autosave would simply save the game and then reload a fresh area when they reload. But if they want more than one save state, they will have to pay for each additional save state as well as maybe a monthly subscription to autosave. I am sorry if they steal this idea.