Never Burn Money

Discovery

Your project has been running for years. It’s been through so many hands that nobody understands the whole thing. It is just too big. But it’s also too big to start over, too much has been invested in it. Unfortunately, the code was not well designed and is just getting worse with each new desired feature. We made a coding standard for all new code going forward, so why is it that things seem to be getting worse and not better? How can we fix this mess of spagetti?

The reason nothing is getting better is that nobody knows where to start from when adding a new feature. The code is so large that when you want to add something new, you don’t know what to build it on top of. There are no layers of the original app, because it’s grown over with the vines of so many special cases that were added by the coders before you. So everyone reinvents the wheel each time, making the project even larger.

But all is not lost! There is still a path to redemption!

What is really wrong is an issue of discovery. The project is so big that nobody knows the ‘best practice’ for this project to do any given task. “I want to make a scrolling list of UI items.” There’s a whole lot of ways to do that, and because this project is so big, there’s lots of examples. But none of them do quite what you need, or it could be more efficient. So you make your own version which does it better. And the next person comes along and knows _nothing_ about what you wrote, so they do it all over again.

The solution is actually very simple: an index document that lists generic tasks and points to specific examples of code that solve those tasks. In the Index, you’d search for “scrolling list of UI”, and it points to an exact file that demonstrates that task. Or it could get even more specific, like “for a few elements” and “for many many elements” and “with group headers”, all pointing to different examples in the code. With each entry it lists a one sentence blurb that clarifies what makes that example different from the others in the category.

One of the bonuses of an index document is that it can be searched easily, as there should not be a large amount of content for each kind of task.

Homework

A couple months go by. There are finally some good examples of doing several things in the project. The index document is pretty stable these days. But the project is still getting bigger somehow. What’s going on here?

We’ve started creating these ‘clean’ examples, but nobody is making them re-usable! They’re only doing copypasta!

The failure is that the app is not being designed in layers. When a new feature is requested, the code is being copied from the template instead of refactoring the template to provide shared code for both the template and the new feature. New rule: to add a feature you must add a layer, not modify existing code. You can refactor existing code to make that new layer, as long as you support the original with its own layer on you refactored base.

This sounds like a heavy burden in such a large codebase, but that will only happen when first starting out. It should happen less and less often, once we start doing it in earnest. This is because the more layers we add, the less special cases will be needed.

RAM

So that fixes that. Right? Not quite. This entire process change is a new coding standard. And if we’re doing our job, the coding standard will continue to improve, covering new situations that we haven’t handled before. Now we have an index file that’s pointing at the old examples, which don’t match the new standard. It’s still a better situation than we started with, true. But how can we tell that the examples are all following the latest standard? We can’t.

Yet again, there is a simple solution to this problem too. We ‘version’ the standard. With human understandable numbers, like ‘2.0.’ As we update code to adhere to a new standard, we simply comment the source file with a header mentioning “Code Standard 2.0.” The rule would then be: if you don’t see a coding standard tag, you’re not allowed to use it. If you see a tag but it’s old, verify that it still meets the latest standard and update the tag.

For ‘core’ objects that is used by many things like UIController, one tag for the header isn’t really enough – instead it gets included in specific method definitions. The idea is the same.

We can even extend this to best practices in our prefabs! A simple single MonoBehavior component that stores an enum of a coding standard version. Along with the Note component for commenting, it will clearly identify that the GameObject and children of that hierarchy are correctly following a given standard, and is therefore safe to use as a starting point for a new UI or system.

And there we have it. A way to untangle the mess without losing your hair.

Words of wisdom

Don’t answer every question your kid asks you. Just because they ask does not mean they are ready for the answer. You have to know if your child is ready. Otherwise you are literally taking away a little piece of their innocence. Life will do that in the fullness of time. Hurrying it along will only take the wonder out of life.

How to be stronger at your [insert creative job here]

This is the most useful thing that a manager ever did for me: he setup a standing, consistent weekly meeting with just me. The aptly-named “one on one” meeting.

 

This meeting is possibly the most powerful 30 minutes of your work week. You can know that what you say will be heard by your boss. We are all deluged with emails and passing each other in the hall while on the way to some other task. Not much chance to focus that way. Your manager has a lot to to consider when dealing with the big picture. They go to all the meetings that you consider a waste of time. They are busy people, even if they are handling a team as small as five. This recurring meeting is a block of time when you know you have each other’s undivided attention.

 

Software is a creative endeavor. It is also all about tradeoffs. Choosing to spend your time on the right problems, and glossing over the stuff that won’t ultimately matter. To do that, you need the big picture. The thing is, you do not have the big picture. Your manager does. How you get it is not through email threads or memos. There is only so much information that you can get from open forums with multiple people, due to politics and other factors. You get that big picture by having a conversation with your manager.

 

If you aren’t asking questions of your manager, then you probably don’t understand the situation well enough. Even if you throughly understand the project, this is time you can learn more about each other on a personal level. This will make it easier to predict each other when decisions need to be made.

 

I still struggle with this even after doing my creative job of computer software and game development for twenty years. If I wanted management, I could have it in a heartbeat. But I don’t like that it would take me from my code. As Capt. Spock said to Admiral Kirk, it would be “a waste of material” for me to take a promotion.

 

A few months ago I was put under a new manager for a new project. His suggestion was the first time I’d heard of it in my career. He tells me it became a priority after reading “Managing Humans” by Michael Lopp. I do not fear end of term reviews, or getting close to crunch time. This is because I know that my manager has told me what to expect, and I was able to tell my manager what I thought we can do about it, all long before it happened.

 

Ask for 1:1 meetings. Make use of them. You both need to know about each other’s expectations and concerns as early as possible.

Warp Shader References

Tonight I did a presentation at a Unity3d user group.
I referenced a few items in the discussion that I thought might be helpful to have direct links to.

Basic Shader
http://docs.unity3d.com/Manual/SL-VertexFragmentShaderExamples.html#simpleshader

Creating Shaders – Surface Shaders, but have a lot of solid basics
http://unitygems.com/noobshader1/#prettyPhoto

Unity Sample Assets
http://blogs.unity3d.com/2014/01/17/new-sample-assets-beta/

Final Shader (with a few tweaks beyond the presentation version)
http://dwulf.com/source/Fudge%20Ripple.shader

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.