Saturday, March 2, 2013

bool GoodEnough == true;

I'm wrapping up my adventures in custom editor land, at least for the time being.

The EditorWindow script actually gave me some serious headaches because of the way I wanted to structure the grid system. The idea was to have three separate grids, each stacked on the z-axis with 32 pixels between them, one for gameplay objects and tiles, one for buildings and other scenery, and one for the backdrop. Problem was, the EditorWindow was set up to find the grid to edit like this when it was opened:

tMap = (tileMap)FindObjectOfType(typeof(tileMap));

which works great when there's only one grid. With multiple grids, each with a tileMap script attached to it, the EditorWindow will only ever find the first one in the list. I tried a number of ways to allow you to choose a grid from within the window, but my first several attempts caused some kind of recursive error that locked Unity up by throwing dozens of null reference errors every second. This slowed down my problem-solving workflow a bit. After a bunch of Googling and cobbling things together, I finally came up with what is perhaps the single ugliest line of code I've ever typed:

allTileMaps = (tileMap[])tileMap.FindObjectsOfType(typeof(tileMap));

Christ, look at that thing. Just look at it. I know what it does but I couldn't tell you why. For good or ill, this monstrosity turned out to be completely irrelevant anyway. After grappling with various methods to expose the members of that array in the editor window, I finally realized that all my trouble was being caused by this line:

tMap = EditorGUILayout.ObjectField("Active Grid", tMap, typeof(tileMap), false) as tileMap;

The culprit was that "false", which is setting the boolean variable "allowSceneObjects", which was keeping me from applying any of my three grid GameObjects within the editor window. This made me think I needed some kind of superstructure to hold every object with the tileMap script attached, which just wasn't true. The embarrassing takeway: just because you found some functional code to copy from somewhere doesn't mean you've solved your problem. If you don't understand exactly what the code is doing, you're as likely as not to cause yourself more problems. I guess this is one of those obvious things that you need to teach yourself the hard way, like a child touching the burner of a stove to see if it's hot.

So here, below, is the final version of my built-in level editor.

That's it - a few data fields, a color picker for drawing the grid, and a Texture2D field that was supposed to show a visual preview of the selected prefab, but which I wasn't able to get working and eventually gave up on. It's more than a little pathetic, but here's the thing: it works. I can click the Active Grid field to select which grid to operate on, then select my prefab "brush", then press 'a' to paint tiles at the mouse location. It's much faster than my old way, and it keeps everything aligned properly, which allows me to get on with building the levels.

I recently listened to a fantastic talk by Jonathan Blow called "How to Program Independent Games" . There's a lot of good advice in there that really brought the dangers of premature optimization home to me in a way I hadn't really grasped before. The key quote, to me, was this:

"I'm a big fan of 'good enough for now', because 'good enough for now' often ends up being 'good enough to ship the thing.'"

We all want our projects to be elegant, sharp, and impressive to our peers. We all respect and want to emulate those heroes of old who had to bend over backwards to cram every possible byte into primitive cartridges and arcade cabinets. We all want to feel smart and capable and professionally ingenious. These are not bad things to want. Ultimately though, as Blow points out in that talk, there are only so many hours in each human lifetime, and there are only so many projects that you or I will ever complete. At the end of your time as a game developer, however that end comes about, which would you rather have: a few completed projects that emphasize clean, correct, bulletproof code, or a bunch of completed projects that emphasize fun, storytelling, cool levels, innovative gameplay and all the other things that motivated you to get started in the first place? It's not a trick question, and it's not a hard choice.

No comments:

Post a Comment