Videoblog #3: Click here
As you may have noticed, I’ve just released another demo. Among the usual, it contains an Asteroids game which I have done for editor testing. The whole game is written in 600 lines of code, which isn’t really much, and half the work was pure content integration using the editor.
I still needed several days for developing it because I was at the same time working on the Duality editor to address usability issues I encountered. For example: To access a Resource in source code, you’d first have to retrieve a reference to it, normally by requesting it from the ContentProvider using a file path. To follow best practices, you’d also have to figure out a way to maintain the reference instead of requesting it again each frame, etc. It worked, but felt so unnecessary. In fact, I got so annoyed I tried to avoid accessing Resources from source code. Whenever I saw those Resources in the Project View I couldn’t help but think “IT’S RIGHT THERE. WHY DO I NEED SO MUCH CODE?”. Well, I don’t, at least not anymore. The editor is now automatically generating all the necessary access code, so a Resource access boils down to accessing a predefined Property.
Another problem I encountered was: What if I created a new Component class in my Plugin and wanted to delete or rename it later – when already in use? It would simply break all Resources using it and there would be no way to recover them.
Unfortunately this wasn’t just bad design on my side. I was using a customized version of DotNets binary serializer. Properly reacting to errors of that kind while loading Resources simply exceeded it’s functionality: Either a Resource is loaded completely or none of it. And it wasn’t just renaming classes that broke Resource files: Changing the Type of a single Field would break any related Content as well.
All in all, this was a complete no-go for usability, so I finally replaced the DotNet serializer with my own binary serializer. It is designed to be as forward- and backward-compatible as possible. Object data can still properly deserialize even when the related class has changed broadly. Damaged Resources will greet you with some errors in the logfiles but are otherwise functional. Any error that occurs while deserializing any type of object only affects that single object – and nothing else.
So far so good – but what if you just renamed a class and want to rescue your old data “as is”, without missing objects? Here’s where the Resource Hacker comes in. What it does is reading or writing objects from files – but instead of creating or accepting actual objects, the Resource Hacker handles only the data structures encoding that objects. On this level, what you get is a tree of data nodes. What would have been unresolved Type references are here simply strings that name the referenced Types. To repair a file that relies on a class you recently renamed, simply use the “Rename Type” action or do it manually by yourself. Then, save the Resource and everything is fine again.
Besides all those big editor changes, there is a rather small new feature in Duality’s core. It is called “MetaData”. Now what’s that? Regarding all global data Duality’s API provides, there are three kinds of it: ApplicationData stores your Game’s name, version number and similar. UserData contains anything you’d normally find in a Game’s “Options” dialog, like display resolution or volume settings.
And then there’s MetaData. It is basically a hierary of key value mappings storing any primitive data you might want to store. The special thing is: This data does not go away when deleting the Game that wrote it – and it is shared among all Duality Games that have been or will be installed on this computer. Why would you need this? Well, you probably don’t.
But what if the actions you took in a game had consequences that persist even after deleting that game? What if your actions had the potential to have consequences in any other game? I think, both are very intriguing ideas – and Duality’s MetaData is hinting you do experiment with them. Making an impact on one game’s world could result in affecting a different game’s world as well – even when only used as a tiny easteregg-reference. But more serious connections would be possible as well. Just imagine playing some RPG and deciding to threaten and rob a trader you meet. It will sure have consequences for your game character, as in many games today. But what if you played a different, unrelated RPG a year later where you suddendly find yourself in that exact same scene – except you happen to be the trader, facing your own former descision – but now as a victim. Working with MetaData could take the weight of a players descision to a whole new level.