Sunday, March 8, 2015

Boxes Full Of Bones

Project_catalan is still a game that doesn’t really know what it wants to be when it grows up, but that hasn’t prevented me from using it as a platform on which to try out new things I’m learning to do. Once I had established the game board as a set of tiles of varying colors (representing terrain types like grass, sand, water, etc.) I became interested in the idea of generating a new version of the board each launch. This is less like sophisticated procedural generation and more like plucking hexagons from the Catan box, but… baby steps.


The method here takes place in three steps. First, a full grid of grass tiles is laid down. Then, starting from one edge, a line of river tiles is placed in a random meandering line, replacing grass as they go. Finally, the tiles on either side of each river tile are replaced with sandy banks. The whole thing is somewhat unwieldy but here’s the river function as an example of what’s being done:

void MakeRivers()
{
 //this could get a little tricky
 //we want to make a river that cuts across the whole grid in a meandering fashion
 //we'll assume at the moment that we only ever want one river
 //first: is this a vertical or a horizontal river?

 int riverOrientation = Random.Range(0, 2);
 if (riverOrientation == 0)
 {
  Debug.Log ("Vertical river");
 }
 else
 {
  Debug.Log ("Horizontal river");
 }

 //now, where does the river start?
 //at a random point along either the top of the left side
 Vector2 riverStartTile;
 int startRow;
 int startColumn;
 if (riverOrientation == 0)
 {
  //start on final row, then randomize column
  startRow = rows - 1;
  startColumn = Random.Range(0, columns);
 }
 else
 {
  //start on final column, then randomize rows
  startColumn = 0;
  startRow = Random.Range(0, rows);
 }

 //now that we have the row/column index, we need to match that up with the index into 
 //tiles[] of the tile actually living in that spot
 //first let's get the world pos of where we think we actually are
 Debug.Log("starting our river at row " + startRow + " , column " + startColumn);
 penPoint = new Vector3(startColumn * width -16f, 0f, startRow * length -16f);
 Debug.Log ("penPoint is " + penPoint);

 //since we're naming the tiles with their row/column numbers, we can use that to find and destory them
 //let's try a straight river first I guess
 int currentRow = startRow;
 int currentColumn = startColumn;

 if(riverOrientation == 0)
 {
  for(int i = startRow; i>= 0 ; i--)
  {
   string tileName = "grassTile_"+i+"_"+currentColumn;
   GameObject tileObject = GameObject.Find(tileName);
   //Debug.Log ("Looking for " + tileName);
   if(!tileObject)
   {
    break;
   }
   Vector3 replacePosition = tileObject.transform.position;
   Quaternion replaceRotation = tileObject.transform.rotation;
   Destroy(tileObject);
   GameObject waterTile = Instantiate(tileTemplate_water, replacePosition, replaceRotation) as GameObject;
   waterTile.transform.parent = tileMapObject.transform;
   waterTile.name = "waterTile_"+i+"_"+currentColumn;

   //bend?
   int bend = Random.Range(0, 5);
   if (bend == 3)
   {
    //ok, we're bending, let's determine how much
    int bendAmt = Random.Range(1, maxRiverBend+1);
    //find bend direction
    int coinFlip = Random.Range(0, 2);

    for(int k = 0; k <= bendAmt; k++)
    {
     //here's where we hop to another column
     //east or west?
     if (coinFlip == 1) //east
     {
      currentColumn++;
     }
     else //west
     {
      currentColumn--;
     }

     //now replace the bend tile 
     GameObject bendGrassTile = GameObject.Find ("grassTile_"+i+"_"+currentColumn);
     if(!bendGrassTile)
     {
      break;
     } 
     Vector3 bendReplacePosition = bendGrassTile.transform.position;
     Quaternion bendReplaceRotation = bendGrassTile.transform.rotation;
     Destroy(bendGrassTile);
     GameObject bendWaterTile = Instantiate(tileTemplate_water, bendReplacePosition, bendReplaceRotation) as GameObject;
     bendWaterTile.transform.parent = tileMapObject.transform;
     bendWaterTile.name = "waterTile_"+i+"_"+currentColumn;
    }
   }
  }
 }
 if(riverOrientation == 1)
 {
  for(int i = startColumn; i < columns; i++)
  {
   string tileName = "grassTile_"+currentRow+"_"+i;
   GameObject tileObject = GameObject.Find(tileName);
   //Debug.Log ("Looking for " + tileName);
   if(!tileObject)
   {
    break;
   }
   Vector3 replacePosition = tileObject.transform.position;
   Quaternion replaceRotation = tileObject.transform.rotation;
   Destroy(tileObject);
   GameObject waterTile = Instantiate(tileTemplate_water, replacePosition, replaceRotation) as GameObject;
   waterTile.transform.parent = tileMapObject.transform;
   waterTile.name = "waterTile_"+currentRow+"_"+i;
 
   //bend?
   int bend = Random.Range(0, 5);
   if (bend == 3)
   {
   
    //ok, we're bending, let's determine how much
    int bendAmt = Random.Range(1, maxRiverBend+1);
    //find bend direction
    int coinFlip = Random.Range(0, 2);

    for(int k = 0; k <= bendAmt; k++)
    {
     //hop to another row
     //north or south?

     if (coinFlip == 1) //north
     {
      currentRow++;
     }
     else //south
     {
      currentRow--;
     }

     //now replace the bend tile 
     GameObject bendGrassTile = GameObject.Find ("grassTile_"+currentRow+"_"+i);
     if(!bendGrassTile)
     {
      break;
     } 
     Vector3 bendReplacePosition = bendGrassTile.transform.position;
     Quaternion bendReplaceRotation = bendGrassTile.transform.rotation;
     Destroy(bendGrassTile);
     GameObject bendWaterTile = Instantiate(tileTemplate_water, bendReplacePosition, bendReplaceRotation) as GameObject;
     bendWaterTile.transform.parent = tileMapObject.transform;
     bendWaterTile.name = "waterTile_"+currentRow+"_"+i;
    }
   }
  }
 }
}
This was the only work I did on this over the winter, as petrov was monopolizing most of my time (see previous post). I returned to it late last month, as it seemed like a perfect test bed for my latest preoccupation: 3D modeling and animation.

I had done some hands-on work with Maya and 3DS Max at various studios, mostly in the context of testing, and I managed to find my way around at a basic level, but these programs are a little too expensive for home use, so I approached Blender, and bounced off, hard. My first crack at it was probably about a year ago, and every so often I would return, a tutorial in hand, and try again, only to end up sliding face first down the learning curve like Wile E. Coyote. In a sense I had been spoiled, as Maya is quite friendly and sensible in terms of its user interface. Blender, by contrast, is full of obscure keyboard combinations, context-sensitive menus, and many different modes the main editor can be in, all of which respond differently to those commands and menus. Ultimately it’s like any other piece of complex software: if you bang your head against it repeatedly, you’ll eventually realize that there are one or two small techniques you've absorbed and become comfortable with. You can then use those as a beachhead and campsite from which to explore more daunting areas. Eventually you may earn enough hard-fought victories to ascend the mightiest peaks, breathe that rarefied air, and proudly don the mantle of “beginner”.

Jokes aside, 3D modeling (not to mention rigging, skinning, and the rest) is a discipline much like programming, in that it’s easy to fool yourself into thinking you know something about it, when you really don’t. A forum post I read somewhere described the gap between a bit of functional programming knowledge and the ability to contribute meaningfully in a programming role at a serious studio as being somewhat like the gap between being able to make yourself dinner and being able to work as a sous-chef at a busy high-end restaurant. I think this is spot on, it applies to many game studio roles, and it’s a good reminder not to get cocky. There is always much more to learn.

My goal in this instance was to add another prototyping tool to my kit. Many of the game ideas I jot down in notebooks require animated 3D models, that is to say, little people moving around. If I couldn't at least rough in this sort of thing, there was no hope. So, I affixed my pitons to the face of Mt. Blender and started climbing.


This is boxman, a Blender model composed of a bunch of cubes joined together. Boneheadedly simple, not much to look at, and in this form totally useless except as a mannequin. I could import him into Unity, but he would just stand there motionless.


This is boxman’s armature, made of a series of “bones” that control his movements. The model is made up of vertices, points in 3D space, that together define the shapes of the boxes. Rigging and skinning a model means that each vertex must be assigned to a bone, so that when the bone moves, its assigned set of vertices are moved along with the bone, in a process called mesh deformation. Since boxman only has a couple dozen vertices, this is about the simplest case you could hope for. Making a realistic-looking character model move realistically involves assigning thousands and thousands of vertices and carefully “weighting” them to control how much deformation the bones can do, to say nothing of constructing the actual animations, transitioning seamlessly between them, and making them responsive to player input. I have a tremendous amount of respect and admiration for the people who do this work for AAA games. Have a look at something like the combat moves in Shadow Of Mordor and it’s quite clear that that this is as painstaking and complex a combination of skill and art as anything a programmer might face.


Here’s boxman getting his walk on via Unity’s Mechanim animation system, which uses a simple keyframe animation interface like you’d find in Maya or even Flash. Of course, you can animate in Blender, then import those animations in Unity and hope you can make them work, but I was quite relieved to discover I didn’t have to. Unity lets you move the bones around in Animation mode using the same transform and rotate widgets you’d use on any other object, so it was a joy to be back in familiar territory. Boxman’s walk cycle is as rudimentary as the rest of him, but the goal here was just to get the basic parts in motion. Pretty can wait. Mechanim also contains a handy state machine interface with variable-based transitions that can be called from script. That is to say, I can give the model a walking state and an idle state, which will flip back and forth depending on if the boolean “isWalking” is true. Then I can make that bool true or false from the movement control script, based on whether the player is touching a key.

Keys bring up the topic of character control, a subject that most projects wrestle with. The original proto-prototype of catalan (known as benko at the time) had a control scheme where you simply clicked the mouse on the point where you wanted to travel, as I had been playing a bunch of Path of Exile at the time and basically wanted to rip off some of the feel of playing that game (no luck whatsoever on that front). I quickly ran into problems because the shooting mechanic involved clicking on monsters, so a slightly misplaced click would send you strolling blithely toward the enemy instead of engaging it, which got frustrating fast. The next iteration was straight-up WASD movement with mouse aim, which was great when the player was an orange cylinder because it didn't matter which way it was facing. To my horror, the box model totally broke this movement scheme.

It’s an interesting and fundamental point of game design that when you introduce anything from the real world, the player expects (quite reasonably) that it will behave like that thing does in the real world. Players will forgive a lack of verisimilitude when controlling cubes or spheres or even spaceships (sometimes), but gosh darn it we all know how people move. The problem with my controls came about when I implemented the player model rotating based on mouse aim. Having the rotation disconnected from movement was no problem for a cylinder, but for a person, it just felt weird that the right arrow was sometimes rightward movement, and sometimes forward or backward movement, depending on the model rotation. Now, this scheme is perfectly valid, and has a long and storied history in the “twin-stick shooter” genre, going all the way back to Robotron 2084, but in most successful cases the movement is sold to the player as realistic in various ways, the most ingenious being to disconnect the upper half of the body from the lower, and orient the legs to the movement vector and the arms to the aim vector. Elegant, attractive, and still a bit over my head technically. I could see upgrading catalan to that scheme sometime in the future, but for now I needed something simpler.

I had a really cute second idea to make the right and left arrows move the player laterally to the facing direction, and even learned just enough about cross product math to make it work, but it turned out to also be a really dumb idea. When the player was facing away from the camera, the arrows worked beautifully; when the player faced the camera their motions were flipped, which was an even queasier sensation than before.

In the end, I opted for a dirt simple approach: the forward and backward arrows (or W and S) work, the side arrows do nothing, the mouse controls aim and rotation. This still doesn't feel great, but it’s workable. I punched up the visuals with some handmade, randomly placed trees and some simple textures instead of solid colors. I animated the water and even replaced the “purple refrigerator” enemies with some kind of bear giant thing that toddles around amusingly.


The whole thing is still a far cry from being fun, there’s nothing much to do and it still lacks any kind of theme or character, but this is really the way I like building things. A lot of designers start with a high concept idea or story and then build the mechanics up underneath that, but I always start with a mental image of a small onscreen interaction. A video game is just a person in front of a screen with a manipulation device (at least until the VR revolution swallows us all whole). If the basic act of interacting with what’s on the screen isn't engaging second to second, then the best story in the world won’t be any use. Refine the gameplay loop, again and again, make that your primary focus, and don’t worry about whether the player is supposed to be a pirate, a cowpoke, an astronaut, or a QA contractor with dreams of glory. Make the fun, and the rest will come out in the wash.

Coming Up
  • Oh, hello Unreal 4. Hello Source 2. Is this an embarrassment of riches or what?
  • A radar for catalan
  • More prototypes, and maybe I'll finish those design docs I keep been talking about






Saturday, February 21, 2015

Always Crashing In The Same Car


It’s dangerous to go alone. The total freedom of solo game development can be its own worst enemy. With no one around to say “hey, maybe rough in feature X and move on”, you can end up caught between your best judgment and the stubborn, dogged perseverance that got you into this mess in the first place. The more of this I do, the more I find that the ability to scope from within a problem, to decide which solutions are good enough for now, to basically Produce oneself as mercilessly as a corporate publisher, that constantly updating self-reflection is the key difference between solo games that are in some way concluded and others that are simply abandoned.

I spent most evenings and weekends of the dark months on project_petrov, often spinning my wheels, or more accurately watching a small model car flip onto its side over and over again.


This whole racing project is a derail in itself. I’ve been working through this (really excellent) Unity textbook which mostly consists of little example game projects where they give you some starter bits and then you complete the game. Everything was going great until I got to the "generic racing game" project. I got into it, then started getting irritated by things like the terrain being inappropriately mountainous (making camera movement in scene view difficult and lighting a chore), the track being punishingly long for the size of the models (making iteration on things like win condition code a chore) and various other minor annoyances. I decided the only way to complete the project to my satisfaction would be to remake it from the ground up, including all the assets. I figured I could whip up some new scripts, hit Turbosquid for some free cars, and maybe put some twists on it so I could have another minor portfolio piece. Expected turnaround time: a few days? This was in November.

My first hack at the track was an interesting idea, I found some outline images of famous race tracks at this cool site, and attempted to use some as height map files on Unity terrain objects. The primary problem with this was the dismal sense of racing in a WWI trench, but there were other problems, for instance I had no easy way to tell whether the cars were on the track or not. Eventually I realized I would need to use some kind of road objects that could send messages about whether a car was touching them. So, the racing trench and its associated materials went into the bin.


Making modular track pieces with Blender was straightforward enough after watching a few relevant YouTubes. My UV mapping skills are still pretty basic, so the road curves look a little stretched and blurry, but I was able to make myself move on from that (which wasn’t hard, because another few nights in Blender was nothing to look forward to).


The muscle car model itself was also simple enough to work with, although the artist “posed” it with the front wheels turned insouciantly to the left, so I was constantly having to adjust them by around 9.6 units of rotation, a figure which grew to haunt me. It didn’t make much difference in the end as I wound up chopping the model into body, glass and wheel meshes and placing each individually as child nodes of either the car body or the car wheels, so I had an invisible cube and some invisible cylinders “wearing” the good meshes like a second skin. I painted each mesh with some basic colored materials, entertaining various dreams of a rainbow panoply of AI opponent cars, and a cel-shaded “Saturday morning cartoon” effect in post-processing, but both of these features turned out to be, thank Christ, out of scope.


Then it came time to make the car go. The book example propels the vehicle by using AddForce on the car’s RigidBody, which works well enough, but as a physical simulation is somewhat like towing the car along behind another car with a cable – the movement force doesn’t come from the wheels, so the simulation is not very car-like. I was determined to do things “the right way”, which meant controlling the car with four WheelCollider objects by applying MotorTorque and BrakeTorque. This was actually fairly intuitive and even fun to implement, and the simulated springs gave the car a delightfully realistic bounciness when dropped onto the terrain. Everything worked beautifully until I attempted to turn the vehicle, at which point it flipped over. Repeatedly. Every single time, in fact.

Anyone who has done time in the murky woods of Unity vehicle physics is probably familiar with self-described Hardcore Developer Edy, a towering genius of video game automobiles who has published some fascinating posts on the Unity forums, describing, among other things, how to keep a car from flipping over. The answer he proposes is simulating stabilizer bars. The idea is, you read data from the WheelCollider to determine how far the spring is extended. When the car takes a turn, the springs on the inner wheels will compress, while those on the outer wheels expand. So, as a spring expands, you impose a downward force on the car body at the wheel location, and the more the wheel threatens to leave the ground, the harder you push down on it. Elegant in theory, but in practice there are more than a few things that can go wrong, and in my case all of them did.

I could not get the damned car to stop flipping over. Some reasons my stabilizer bars might have failed:
  • The car may have been out of scale to the Unity physics system
  • The car’s rigidbody mass and center of gravity settings may not be compatible with the stabilizer code
  • The car model exported from Blender may have some qualities that don’t play well with the physics system and/or the stabilizer code
  • My WheelCollider settings may be incompatible with how the stabilizers work
  • I may not be applying the downward force effectively, with the right amount and at the right location
  • Despite extensive visual debugging to make sure X really is X, I may be misunderstanding what the stabilizer code is actually doing
  • My math deficiencies may have gotten the best of me (the stabilizer code uses Transform.InverseTransformPoint, which I can’t honestly claim to completely understand)
  • The WheelColliders themselves may be in some way suspect. I have nowhere near the knowledge to takes sides on Edy’s post about a purported scandal in wheel town, but nobody from the Unity dev community has come along to tell him he’s wrong, so who can really say?

All interesting lines of inquiry, for someone with half a dozen spare lifetimes to spend faffing about with wheel physics, but I had already squandered too much time on the problem. Finally, I found a brutal hack and wielded it like a hatchet. Behold my shame:

downforce = -veloMag * rigidbody.mass * 3f; //sSHHH it's a MAGIC NUMBER son
downvector = new Vector3(0.0f, downforce, 0.0f);
rigidbody.AddForceAtPosition(downvector, transform.position);

The faster the car goes (veloMag is the rigidbody’s velocity.magnitude), the harder I press down on it at the center. It’s like racing with the veritable Thumb of God on the car roof the whole time. Now, any future development work would surely start here: I’m confident that I could lower that value and tweak various other parameters until I reached a compromise where the car would resist flipping, but retain some of the car-like bounciness the WheelColliders provide. As it is, I’ve more or less come all the way back around in terms of realistic simulation. This solution is hardly more “car-like” than just applying force directly to the car, all the interesting wheel spring behavior is getting squeezed out of existence, like the dynamic range on a Red Hot Chili Peppers album.

Regardless, this allows me to glue the car to the ground, finish the scenery and UI, put some basic game logic in place, and close the loop on the project as a portfolio tech demo. It’s a racer, just not a very compelling or well-realized one, and it’s not exactly meant to be. Although I have some interesting ideas on where it could go, and I may spend more time on it later, I’m not taking this thing to Early Access.

Here's where I confess to not particularly loving racing games. Oh, don't get me wrong. Pole Position is just as iconic to me as Galaga or Moon Patrol, and the arrivals of the Stun Runner and Hard Drivin' cabinets at my local arcade were earth-shaking events at the time. I just mean to say that I never planted a stake in any modern racing franchises, never had a Forza career or bought a faux steering wheel. So why make one? Primarily due to being at the racing chapter in the textbook I was working from, but just as importantly out of a self-imposed need for portfolio diversity. For some dumb reason I feel like a proper game designer should be able to whip up anything from a shooter to a stealther to platformer, in 2 or 3D, in enough detail and with enough quality so that it could convey whatever the cool new twist is without stumbling over the set dressing. It's a fine notion, but it turns out that maybe racing is one of the less trivial genres, from a gameplay design point of view.

And, without getting too grim, this work is hard enough to justify as it is. When I wasn’t day jobbing on the fringes of the industry, I spent the dark months flitting from studio to studio whenever a designer role came open on the job boards, shaking hands and telling my life story over and over, trying to convince someone, anyone, that yes, I am actually competent as a game content designer, and not being able to convey that impression in the slightest. I’m hoping that all this portfolio work will pay off, but it’s hard to believe that anyone will care. The studios want, and in most cases can afford to wait for, a designer with years of commercial experience on the exact subgenre they’re putting out. I’ve been rejected on the basis that “we’re looking for someone who lives and breathes subgenre X”, which, I suppose I’d want that too in their position, but it points to a pretty dark future for someone whose resume looks like it was written with a shotgun. I’m slowly trying to find a way to accept that I may never be employed as a creator again, that the rest of my career may be an endless string of exploitative and unrewarding QA contracts. I have to make a conscious decision every day to not believe this, because the feeling of believing it is like the feeling of being on fire. Nobody likes being on fire.

Coming Up
  • more prototypes
  • project_catalan upgrades
  • some non-Unity experiements
  • some game design docs for larger projects