Unity to Godot port complete!!!
Alright, so ... deep breath, port has been FINALLY completed! It took exactly 6 months, unfortunately that was exactly my prediction, as I was secretly hoping to be done sooner. Where did the time go?
- The C# code was ported pretty quickly, in the beginning: it's C# to C# after all, so removing Unity calls wasn't that hard, for most of it
- The developer GUI was ported pretty quickly, at the end: I did that a few weeks ago. Replacing Unity's IMGUI with Dear ImGui. It was a breeze I'm telling you.
- The rendering pipeline had to be written from scratch, this took quite a while. Instead of using Unity's rendering code and GameObjects, now I use a single Godot "sprite" on which I render the entire game via the low-level Vulkan-based API. This gives me very good control, allows me to introduce bugs and has caused me a few architectural headaches, but it's all working fine now.
- The shaders took time and energy to port, as I had to rewrite them from Unity's Cg-like to GLSL, plus I had to refactor quite a few shaders. To make matters worse, because the Vulkan API is so low level, simple uniform variables are not possible, and things have to be packed in carefully-aligned buffers. Fussy, fussy, fussy, but done.
- Dynamic texture reading/writing took a bit of time, as it's an important element, especially for sprite composition
- The native plugin needed zero time to port - hah! The beauty of having a separate modular piece of software, we just plug it in new engine, with the same bindings because I'm still using C#
- Refactoring. I did plenty of refactoring, but nowhere near as much as I need. But I'm happy with some of the changes. Refactor affected mostly graphics, as that's where old code HAD to be removed, and be replaced with new things. Another refactored element was the game state approach, as I had to make a few separate stages like world generation, population with resources, population with cities, and then the game. I wanted to have something modular like this because I need to start testing UI, and I want to test it on these early world generation screens.
- Adding new features. During this time I did manage to add a few new things. For example the sound system is a bit better as the way sounds can be assigned to surfaces/actions/etc is nicely flexible. I'm still nowhere near demonstrating this well, because I need lots of sounds. But the framework is there.
- New bugs! Yes, unintentional, but there is so much new and reshuffled code, that new bugs have been added and mixed with the old.
So ... what now? Well, first I need to fix a few more bugs. I have been in bug squashing mode for a few days, and plenty more to be done. I need to start a bug tracker with bug severity, that would be helpful, because now bugs are lines of the form "bug: blah" in my TODO file. Maybe that will change to "bug-x: blah" where x is the priority level, possibly that's as much complexity I'm willing to add. At the same, I have some feature ideas that I want to implement, and this can break the dullness of constant bugfixing, but it means that more features = more new bugs. Cost of keeping my sanity and motivation.
Developer GUI improvements
This week, among the bug fixes, I improved the developer gui a bit. Three major points here:
- All flyweights can be edited (mostly). My JSON-defined configuration database is big. So far, I had no way of easily changing that on the fly. Now, with the help of C#'s reflection and ImGui, I can write a little bit of code that allows editing of the entire configuration database (hundreds of classes and objects). The magic is that we can process classes easily by iterating through the class variables and calling appropriate ImGui controls. This is super-powerful, and means that now I can adjust configuration on the fly and see what settings work best. Still can't save the updated configuration, but that's trivial. Support for changing a derived class altogether should also be added soon.
- TempPool allocation. I had some custom code to allocate temporary objects from a pool, but now I've added some GUI and tracking so that I know what's tracked where, even source code file and line. That's super useful in the case of any leaks, which are easily reported. It's like a manual memory allocator really at this point
- Log channels. I've added some functionality that I used to have in Unity wrt log channel granularity. I can quickly set the log level of individual subsystems (e.g Time, Gfx, Sensory), or set it globally for all, and can clear/flush the log. This allows targetted logging during debugging, e.g. set global log level to "error", set Gfx and Time to "info", clear/flush the log, perform desired actions that reproduce graphics/timing bug, then flush log and inspect it. I've even added a button that automatically opens the log file in Notepad++, it's sooo convenient.
Bug fixing
Ok, I'm not a fan of changelog updates, so I'm not going to dump all the esoteric commit messages (unless you're curious!), but I thought I'd take a note for each, and they ended up being around 30 fixes, without counting new features e.g. the GUI stuff above.
Overall, I think this was a good week. And I can tell to my brain that "port is complete" so that I can move on to other things without having the feeling that I'm still in Unity-to-Godot porting limbo.