Dev time was extremely limited this week. After reprioritizing Release 3 features, my plan for the week changed and I ended up working on the save system. This was functioning in Release 1 but I haven’t updated it for all the features and refactoring done in Release 2. So much has changed that I’m basically starting over. I’m also having to rework some classes that contain a mix of data that should be saved and data that shouldn’t or can’t be saved (e.g., MonoBehaviours). I read a lot of articles and watched a lot of videos on save systems in Unity. Most of what I found was aimed at beginners and only covered the basics. This video was helpful, but I didn’t like having to create a new temporary object and save and load methods with explicit setters and getters; it’s slow performance-wise and difficult to maintain. I’d rather just isolate the data that needs to be saved and serialize it. Either I haven’t discovered the right pattern, or saving complex data in Unity requires a lot of effort and there’s no way around it. I could put all of an object’s state data into a single plain C# class, but then I couldn’t use composition to build game objects. I could isolate the state data on each game object component, but then I’d have to individually serialize the data in each component, or aggregate the stage data spread across the components first. Ideally, the save system would simply save and restore game objects marked for saving and restoring. This is technically possible in Unity, but from what I’ve gathered it’s not advisable. Anyway, after some analysis paralysis, I started implementing the new save system starting with the map. Once a monolithic class, the map now simply contains its dimensions, a cell collection, and half a dozen other collections that are only used for procedural generation, such as the room collection. I don’t believe I need to save the procedural generation data after the map is created, so I’m not going to worry about saving that data for now (ideally, this data would be in a class specifically for map generation that is destroyed after the map is created; will refactor in the future). So, the bulk of the data being saved is the cell collection. Each cell contains multiple attributes, including value and reference types. By default, the serializer I’m using (Json.NET) serializes objects by value. This is a problem for “type” objects. For example, each cell has a cell type, such as a wall or a floor. Each cell type has many attributes. By default, Json.NET serializes all of the attributes in the cell type for each cell that has that cell type. This increases the size of the save file significantly and loses the reference to the original cell type object. I solved this problem by adding an attribute for the cell type’s unique id to the cell class. The advantages of this solution are 1) less data written to file and 2) when loading data, the reference to the cell type object can be restored by retrieving the cell type from a dictionary using the unique id as the key. I applied this pattern to other attributes as well, such as actor types and item types. As of now, the map successfully saves to file, but loading hasn’t been implemented.
Other than that, I briefly descended into a rabbit hole on story-driven procedural map generation. This came out of the map generation work I did last week on room types. I want maps to have some coherence or purpose rather than just being a random assortment of rooms, and cohesion across levels that is driven by an overarching procedurally generated story. Ideally, the player’s actions could alter the story and influence future levels. I created a conceptual framework for doing this and implemented some of the building blocks. However, after reprioritizing Release 3 features, this is on the backburner for now.
Next week, the goal is to get saving and loading working again and start on the hotbar.