All games are engines

Write your game code so it can be re used, and your next game benefits from it. Ideally only the things that make your game unique will not carry over to the next game.??

Here’s the setup: I spent time fixing up a chunk of code for use in our asset pipeline. However, my lead coder had his own feelings about an addition I had made. What follows is my response.

 

It appears to me that there is a fundamental difference between how you and I approach coding. Please correct me if you feel this is wrong:
– you are concerned with making changes for the sake of this project.
– I am concerned with making changes for the sake of *all* projects.

This strong typed id is a perfect example. You do not feel it is a good fit for this project. Okay, I can certainly live with that. But not every game team will necessarily make that choice. And that is the core difference.

At the same time, I do not feel that we should have custom versions of scripts and sources that are specific to particular games. This leads to maintenance nightmares. It is better to have one reusable script that has options to allow each targe team to make those decisions for themselves. Then when bugs are identified and fixed by one team, Then all teams can share the knowledge without having to import it into their custom version. It just “works”. Not to mention that additional features can be created and shared to all with minimum of fuss.

There is a limit to how much options should be available before the script is fundamentally different from the original base one. But a properly designed script or bit of code will only be doing one task, and most of the time, there is rarely more than one good way to do that task. This very fact automatically limits how many options are needed in the first place. If the task is so different that it needs a lot of extra support options then it is probably doing a completely different job and is no longer sticking to one task, and should be decomposed into multiple sources instead.

One script = one task. ??Likewise, the thrift making script does one task, and is fairly compact. I do not believe it should be split into multiple files because it already adheres to this principle. To split it would make the code harder to read, not easier.

Just because it is capable of the strong typed Ids does not mean you have to use it that way. It still processes a non typed id in the same way it did. As proven by converting the existing data set. It is improved with some other cleanups that are related.??

 

I feel that few game coders consider these kinds of issues all at once. And I think we could be making much better games if we were to simply design the basic stuff reusable. Much more of our games is basic stuff than most want to admit.

Boycott Bad Developer Tools!

I’ve been at this game coding thing a long time now. Long enough that I’ve noticed a difference in attitude of game coders who have been around as long as I have.

 

We wonder why our development tools have gotten *worse*, not better.

 

Agile and other high level methodologies are a fine thing. I make use of their ideals all the time. But that’s not what makes me productive. What makes me productive is that I’ve chosen the right tools for my job. But not the mainstream tools – because the mainstream tools have gone to the dogs.

CodeWarrior – anyone remember that superb Metrowerks development environment? That was the one reason I stayed with Macintosh computers for so long. At the time, Windows had Visual Studio. Which was an all-in-one window, covers the whole screen with wasted UI, sloppy, slow development environment.

The only IDE to surpass it was Xcode 3. Apple clearly learned a lot. And it was a superb run. Yes, they defaulted to an all-in-one interface, but they were smart enough to embed a way to break it up into the highly effective multi-window design of CodeWarrior. They knew where their bread was buttered.

 

There is an online radio show by a couple of smart guys. Apparently they are the guys behind the (most awesome) RAD game tools. I was using their stuff twenty years ago. And I’m both pleased and impressed to see they are still going strong. The Jeff and Casey Show, April 2014. They were expounding upon how they don’t care about high level tools when our low level tools have progressively gotten worse and worse over the years.

One thing they said rang so very true with me: we need to boycott these crappy development tools until the vendors realize that this is crap. Visual Studio not updating variables immediately during single steps? Two minutes to do a single run in Xcode just to install a *debug* version on an iOS device? And we won’t talk about 3 minutes for building the dSYM file. How can we possibly get anything done when we are spending so much time just waiting for our computers to do what a decade ago took half as long?

And yet we are in no real position to do anything about it besides cross our fingers and hope something changes. We have to use these tools because they are the only way to get our code past the gatekeepers. Or are we?

 

So I am productive – because I don’t use the gatekeepers. I use Unity3d, which lets me do everything in a very well designed *simulator*. (It’s a shame the MonoDevelop IDE is terrible, but it’s still faster than Xcode or anything else.)

 

Boycott these crappy development tools – and make better ones!

Embedded IDs in Network Structures

Here’s an issue I’ve been wrestling with and cannot come up with a solid solution:
Should IDs be included inside structures, or is that metadata that should be encapsulated at a higher level?

Here is a more concrete example. We are tracking the state of a given Fighter in the game. This is a stateless server environment, so we need to transfer as little information as possible, but we must still describe everything. We assume there is a larger datastore on the server that has additional constant “definition” information for each Fighter.

Here is what the definition looks like for the external metadata version. Incidentally we are using Thrift, but the issue is the same in any environment.

// current state for fighter.
struct FighterState {
1: required i32 CurHealth;
2: required i32 MaxHealth;
}

struct FighterList {
// indexing
1: required map<FighterID,FighterState> fighters;

// connects a fighter to the definition datastore.
2: required map<FighterID, string> definitionIndex;
}

Immutable information is clearly separated from mutable. However, every method that needs to operate on a Fighter requires two parameters: The FighterList and the FighterID to identify which one is involved.

So this is what the information looks like if we encapsulate it all in one location.

// current state for fighter.
struct FighterState {
// indexing. this is immutable.
1: required FighterID FighterID;
2: required string DefinitionID;

// actual state
3: required i32 CurHealth;
4: required i32 MaxHealth;
}

This produces a mixed-mutability object. This feels less than ideal. Every time I transfer the state between client and server, I repeat the DefinitionID. However, if I want to pass a Fighter to a method, I can simply pass the FighterState and have enough information.

So let’s approach this in another way. What if we use compositing?

// current state for fighter. This is mutable.
struct FighterState {
1: required i32 CurHealth;
2: required i32 MaxHealth;
}

// immutable
struct FighterInfo {
1: required FighterID FighterID;
2: required string DefinitionID;
}

// combine them for runtime use
struct Fighter {
1: required FighterState State;
2: required FighterInfo Info;
}

We have now clearly separated the mutable from the immutable. We also can pass just the one Fighter to methods. But this feels very wordy. Also, the needs of the client and the server are slightly different. The server needs the complete “view” of the fighter definition, while the client can use a trimmed down “view”.

This can be simplified by merging the FighterInfo into the Fighter. Not quite as clean of a separation, but it maintains the mutability model.


// current state for fighter. This is mutable.
struct FighterState {
1: required i32 CurHealth;
2: required i32 MaxHealth;
}

// Network view of the fighter. It includes a mutable base, but the additional fields are immutable.
// This is minimal information for sending across the network.
struct FighterNetworkView {
1: required FighterID FighterID;
2: required string DefinitionID;
3: required FighterState State;
}

// the server is now able to add additional information – the complete definition for the fighter.
// This no longer must be handled in Thrift, it can be a subclass of FighterNetworkView, which simplifies accessing.
struct FighterServerView {
1: required FighterNetworkView Network;
2: required FighterDefinition Definition; // we no longer need to look this up externally
}

Now it is implied that only the base FighterState is mutable, while preserving just one parameter to methods. Additionally, this assists unit testing because there is no longer an external dependency to grab the Definition information at each use.

This still feels slightly wrong however because we are making a FighterServerView technically “mutable” because the base class is.

On the other hand, I’m used to SQL tables where IDs are regularly included with the data rather than external, necessary for lookups.

Opinions anyone?

Bottom-up Dependency Injection in Unity3d

This is a potential solution to the dependency injection problem. That is, when an object needs access to some shared resource, how does it get a reference to it? Shared resources are typically handled in games as Singletons, but in truth that is not strictly necessary. Some of those resources could be unloaded and reloaded on an “as needed” basis. Why do we care? Because to test the client object, we could ideally use something completely different for the datasource and the client will be none the wiser.

Why not Editor references, or prefabs? Because a reference is meant for indicating a controller-controlled relationship. The object with the reference is the controlling object, meant to make changes to the controlled object. If we were to add references to dependancies as well, then it would give us dependency injection. The catch is, if we later want to change the object we depend on, perhaps to change the specific subclass, the reference that the child objects have can be invalidated. Then you would have to manually reconnect every single object reference to the new object, manually.

This goes the same for prefabs. There are ways of keeping the prefabs sane, but one change (like deleting an unrelated GameObject from the prefab) will require a new prefab, invalidating every reference to (and from) it.

 

This solution is designed for game/application code. It is not designed for separate libraries or assemblies. it also is designed as simple as possible. Therefore some performance costs are incurred so that the final code can be simpler.

First we define how a piece of game code will request a dependency. Perhaps it should look something like this:
SharedObject thing = SharedObject.instance;
That sure is pretty. The only gotcha is, when our SharedObject is an interface, we can’t declare an instance with a static property. Okay, then let’s get lower level.
SharedObject T = DependencyRegistry.Find();
Not bad. Brief, but effective. We intentionally avoid the DependencyRegistry.instance.Find<>() pattern because it’s more wordy. We will never be passing the DependencyRegistry as a parameter to a method, for example.

What if the caller needs to choose from a list of providers of the same class type? Perhaps a list of database connections. We will consider this a rare case, as most of the time you just need a single class or interface implementation. In any event, this is type-safely solved by creating a wrapper class or interface that offers the list in whatever form makes the most sense for the task at hand. It could be a list object, or even a custom class that has a field for each specific instance as needed.

That SharedObject.instance thing was nice though. And it would work perfectly fine for any concrete class. At first blush, it would seem inconsistent to allow two ways of accessing the same feature. However, the mindset behind an interface is very different from a class, so we can allow it. We just need to remember that a concrete provider that isn’t a singleton has to define an instance getter that resolves to the Registry.

Okay, API defined. How do we implement it? Clearly some searching is needed. Initially I considered using the Transform Hierarchy to search, but I realized that most objects in that tree will not be providers. Additionally, some of the providers may not even be in the same Transform root of the hierarchy. This leads me to creating an object registry. That is, a central list of objects that offer themselves as datasources.

 

The registry itself is as simple as a list of objects. We chose weak references so that a provider could use the OnDestroy or IDisposable interfaces to know when no consumers are making use of that provider any longer. Also, there should be relatively few providers at any one time, so the ram overhead should be negligible.

As an optimization, we assume that objects added later to the list will be more relevant to the potential consumers than the earlier ones. Therefore when searching we start at the end and work our way backwards.

Getting added to the registry is as simple as asking to be added. To prevent waste, we dedup additions. This can be safely done from within a MonoBehaviour’s OnEnable() method. This will be called before Start(), and work correctly from within prefabs as well as scenes. Likewise, removal is easily done during OnDisable().

It is not required that you add/remove yourself to the registry at these times. You can add or remove yourself at any time. The only things that care are the potential consumers. It is perfectly possible for a consumer to sit in a Start coroutine and wait for the provider object to become available.

You can grab the full source as described from
http://dwulf.com/source/DependencyRegistry.cs

Advertising Done Right

Your attention please. Please yell if you’re paying attention. This is worth watching. We will wait. YouTube Video

This is how advertising should be done. I don’t really know or care anything about the product, or the company behind it. But seeing this video changes my mind. *This* is exactly how advertising should be. It changes my mind, without making me feel bad for doing so. Yes, it uses the “tug at my heartstrings,” but it is more about hope than it is about selling something. It respects the viewer, instead of pandering to them.

This is worth pointing out as an example of what this world should be more like.