Readit News logoReadit News
jolexxa commented on Display Scaling in Godot 4   chickensoft.games/blog/di... · Posted by u/jolexxa
jolexxa · 6 months ago
This is a write-up of display scaling and the new tools developed that allow you to correct for the native display scale factor in Godot — something you can't really do without native calls on macOS and Windows.
jolexxa commented on Serialization for C# Games   chickensoft.games/blog/se... · Posted by u/jolexxa
flohofwoe · a year ago
If I learned one important lesson from writing savegame systems: don't directly serialize your entire game state on the "game object level" (e.g. don't create a savegame by running a serializer over your game object soup), instead decouple the saved data from your game logic internals, have a clear boundary between your game logic and the savegame-system, keep the saved state as minimal as possible, and reconstruct or default-initialize the rest of the data after loading saved state.

With that approach, a language-assisted serialization system also looses a lot of its appeal IMHO (although it can still be useful of course for describing the separate savegame data format).

Also: resist the architecture astronaut in you, especially savegame systems are a honey trap for overengineering ;)

jolexxa · a year ago
All very good advice that I feel deeply. I think I fell into the honey trap some time ago, but I've made peace with that — the tools I'm making will probably do more good than any game I could finish making, at least for now.

Jokes aside, though, I do try to dog-food my tooling as much as possible. I maintain a Godot/C# 3d platformer game demo with full state preservation/restoration (<https://github.com/chickensoft-games/GameDemo>) to demonstrate this.

By the time I've finished writing tests and docs for a tool, I've usually identified and fixed a bunch of usability pain points and come up with a happy path for myself and other developers — even if it's not 100% perfect.

I also have a bunch of unreleased game projects that spawned these projects, and even gave a talk on how this stuff came about (<https://www.youtube.com/watch?v=fLBkGoOP4RI&t=1705s>) a few months ago if that's of interest to you or anyone else.

The requirements you mentioned in your comment cover selectively serializing state and decoupling saving/loading logic, and I could not agree more. While you can always abuse a serializer, I hope my demonstration in the game demo code shows how I've selectively saved only relevant pieces of game data and how they are decoupled and reconstructed across the scene tree.

Also probably worth mentioning the motivation behind all this — the serialization system here should hopefully enable you to easily refactor type hierarchies without having to maintain manual lists of derived types like System.Text.Json requires you to do when leveraging polymorphic deserialization.

Manually tracking types (presumably in another file, even) is such an error-prone thing to have to do when using hierarchical state machines where each state has its own class (like <https://github.com/chickensoft-games/LogicBlocks>). States as classes is super common when following the state pattern and it is well supported with IDE refactoring tools since they're just classes. Basically this serialization system exists to help save complex, hierarchical state without all the headaches. While I was at it, I also introduced opinionated ways to handle versioning and upgrading because that's also always a headache.

jolexxa commented on Serialization for C# Games   chickensoft.games/blog/se... · Posted by u/jolexxa
Madmallard · a year ago
RunUO has an implementation of this and it's like 25 years old but still worked really well
jolexxa · a year ago
I really like this implementation, but it's probably worth mentioning here that RunUO and other tools like it are solving the problem at a layer of abstraction beneath what I was introducing here.

The serialization system I am providing here actually leverages System.Text.Json for reading and writing data — it's more concerned with helping you represent version-able, upgrade-able data models that are also compatible with the hierarchical state machine implementation I use for managing game state.

jolexxa commented on Serialization for C# Games   chickensoft.games/blog/se... · Posted by u/jolexxa
kogir · a year ago
This seems to cover many common pain points, but I’ve written my fair share of .NET serializers and for anything I build now I’d just use protocol buffers. Robust support, handles versioning pretty well, and works cross platform.

I’d like to know their reasons for making yet another serializer vs just using pb or thrift.

jolexxa · a year ago
This is a good point. I don't think anyone wakes up wanting to make a new serializer. At this point, I was already pretty deep into making and releasing tools for my game projects so doing this didn't seem like such a stretch (although it actually ended up being one of the hardest things I've ever done).

A lot of small to mid-size games (which are the focus of the tools I provide) want to save data into JSON, whether it is to be mod-friendly or just somewhat human-friendly to the developer while working on the game. Not familiar with Thrift, but PB is obviously for binary data and has a focus on compactness and performance, which isn't the primary concern on my list of priorities for a serialization system. My primary concern for a serialization system is refactor-friendliness. I want to be able to rework type hierarchies without breaking existing save files, or get as close to that as possible.

I suppose you could say I'm only really introducing "half" of a serialization system: the heavy lifting is being split between the introspection generator (for writing metadata at compile time via source generation) and System.Text.Json (which handles a lot of the runtime logic for serializing/deserializing things).

jolexxa commented on Serialization for C# Games   chickensoft.games/blog/se... · Posted by u/jolexxa
wheybags · a year ago
In my experience, the pain of dealing with changes outweighs the pain of dealing with boilerplate, so it's better to explicitly write out save and load functions manually than rely on reflection.

Also means you can do stuff like if(version<x) { load old thing + migrate} else {load new thing} very easily. And it's just code, not magic.

jolexxa · a year ago
That's essentially what this system does — it identifies the models and their properties that you've marked as serializable at build-time using source generation, and then allows you to provide a type resolver and converter to System.Text.Json that lets you make upgrade-able models with logic like you just described.

The assist from the source generation helps reduce some of the boilerplate you need, but there's no escaping it ultimately.

jolexxa commented on     · Posted by u/jolexxa
jolexxa · a year ago
Hi friends, I worked really hard on trying to make serialization and complex save/load easier to implement for C# Godot games (a lot of it is just pure C# and works for other stuff, too).

This serialization effort ended up resulting in the creation of a number of new tools, as well as major updates to existing ones.

As usual, I am always open to feedback and questions. Just wanted to share in hopes that it helps someone and maybe get some critical insight into technical improvements, if you spot something.

u/jolexxa

KarmaCake day75July 7, 2022
About
I really like making things!
View Original