Friday, November 29, 2013

In The Trees, In The Weeds


I've entered some impossible place where every task takes twice as long as the previous task. The goal was and is still three playable levels, with a few neat unlocks and a couple more enemies. Level 2 is supposed to represent Seattle's Queen Anne neighborhood, with its imposing hill spreading up the right side of the screen. There's not much platformer action to be had on a single steep hill, so what to make platforms out of?

Pioneer Square had the easy visual metaphor of that big iron lattice pergola (yeah I had to look up what the hell that thing's called), but nothing so obvious exists in QA. Trees were an obvious solution, I remember planning to have a few in one area or another, and they are about as classic a platform-disguise trope as you can get. One problem that arose quickly is that I can't draw a convincing tree.

The method I ended up with is far from ideal but somehow the appearance was able to barely pass my internal editor. After all, I had to come up with something. I drew out the trunk and each branch, as well as four squiggly bare "sub-branches". I flipped each of the sub-branches for a total of 8, then took a green 32x32 "leaf" and used it as a stamp across all of those, as shown here:



Then each individual branch of the tree gets stamped with a selection of these sub-branches and attached to the trunk. I made each branch its own gameObject because I had this idea of scripting them all to sway gently in the breeze, which I may still do but whenever I picture it now it looks like it would be unsettling, which is maybe a point for and not against. I've thought also about doing a lighter green semi-transparent globe of leaves behind each tree to give them a more traditional tree-like appearance, but I'm not sure I could really get it right.

The tree branches also presented an opportunity for varied routes through the level, something more interesting than flat planes, so I rigged up the hinged box colliders shown at the top. Now, to do this kind of platforming right, you need for the player to be able to pass through these colliders when jumping from beneath. You can't make them go to the end of each branch and then try to reach the one above, it wouldn't work. There are many ways to do this.

One important point is that each face of a collider only works in one direction. So theoretically the easiest solution would be to use, instead of box colliders, mesh colliders with a single quad sprite mesh, facing up. Player passes through from the bottom, collides on the way down.

I didn't go with this, because some early experiences and research led me to understand that single plane collision with a 3d object in a 3d environment is inherently just a bad idea. You're subject to "tunneling", where the surface area that records a hit is so narrow that your colliding object can pass through it between the high-speed snapshots your physics simulation is taking of the game state. This Unity Amswers user sums it up. 

Another solution, likely quite easy for many, would be to take the standard Unity box collider, import into Blender or what have you, remove the bottom, and export back to Unity. Custom collision mesh, very nice. Problem is I don't have any skill points in 3D modeling.

"It's free, there are tutorials, you could learn to do that much in an afternoon!" Yes but I have a series of goals here and I can't be endlessly sidetracked. Maybe my next game will involve custom 3D models but this one doesn't and I need to finish it with the tools at hand. That's the theory anyway: when everything is taking twice as long as you thought, don't go looking for hours of work to put between you and the next thing, just find a better way to solve the immediate problem. You spec the talent tree you're working with the XP you have and you play your class, you don't try to be All Things At Once.

So it turns out Unity has a feature called Layer-Based Collision Detection that's actually more or less perfect for this. The tree branches go on one layer, the player goes on another, then we ask a question, is the player moving up?
 
void CheckForPassPlatform()
{
 if (!controller.isGrounded)
 {
  jumpThisPos = transform.position;
 
  if (jumpThisPos.y > jumpLastPos.y)
  {
   Debug.Log("ignoring branches");
   Physics.IgnoreLayerCollision(10, 13, true);
  }
  else
  {
   Debug.Log("hitting branches");
   Physics.IgnoreLayerCollision(10, 13, false);
  }  
  jumpLastPos = jumpThisPos;
 }
}

I probably don't need that isGrounded really. Like I said it's more or less perfect, but the less happens becuase of my hinged collider platforms. There are occasionally cases when the player is coming down from the apex of a jump that took them halfway through the platform above. The player won't hit the thing they are already in the middle of, but if the player is also moving sideways they will bump into the next piece of collider at the hinge. The player is heading down so the collision layers are reading each other, which we would want if the player were above the collider, but since the player is to the side, we don't want this.

Well, I know there's an answer here, and I know it involves raycasting, so I've been investigating that, but I find raycasting difficult to use. The ray is invisible, so you have to draw it using Debug.DrawRay, but Debug.DrawRay takes a different set of arguments than Phsyics.Raycast, so how do you know your debug line is really the same as your raycast line?

I guess when the player is coming down from a jump, we raycast from the player's center to a point just beneath the player's feet. If there is a collision there, we allow the layers to collide, otherwise we don't. This should allow the player to pass through side collisions on the way down.

I really hope I don't get any cool ideas like this for level 3.

Tuesday, November 5, 2013

Detours


I knew I should get some work done over the weekend, but I couldn't bring myself to fire up the old platformer so, still slightly hungover from a marathon Path of Exile session, I set myself this question: what could I do in Unity to cobble together the basics of a 3/4-top-downish, click to move-or-kill-or-loot type game? I've been daydreaming of various lo-fi recombinations of Zelda DNA for a long time, and a cold grey Sunday seemed like the proper time to take a swing at it.

Predictably, I didn't get far enough to call the result a game, but it's certainly something that can be clicked around in, which you can do here if you so desire. A few notes follow on how it went down, what I learned and what might come after.

I flipped my tile grid from the platformer on its side, and was able to neatly arrange some colored quads as crude terrain. The tile map code will allow me to paint big maps easily, if that becomes something I'd want to do. A third person follow camera was as easy as creating a camera, positioning the view where I wanted it, and making that gameObject a child of the player. Snap!

The Diablo cursor that travels all over a 3d map in response to a 2d mouse position also turned out to be a lot easier than I anticipated, and doesn't even require a bunch of funky juggling of world and screen coords. All it takes is a raycast through the player follow camera. The conveniently provided Ignore Raycast Layer also saved me some trouble. The entire thing is two lines:

screenPos = Input.mousePosition;
mouseRay = this.camera.ScreenPointToRay(screenPos);

transform.LookAt... seriously? You can do this? I'm going to try to pretend all that time I wasted on older projects doing Quaternion math just never happened.

Vector3.MoveTowards is also pleasingly simple. You don't unfortunately get any easing this way, and poking around in the math library always gives me a headache, so I eventually hacked in something I could live with: if the player is within 1 or 2 units of the destination, their speed is halved. This almost looks like a lerp if you kind of squint at it. 

Some weapon experiments quickly led me to the rigidbody system. The idea of a Zel-diablo-like with real physics projectiles is intriguing, though I'm not sure it will ultimately be worth doing. My first attempts featured arrows that tumbled like poorly winged footballs, which is kind of interesting on its own.. what about a game where you start out as a completely inept archer? 

The main idea I wanted to bring to life here was a mental image of the player confronted by something like a rampaging bear, which would continue to approach as the player peppered it with arrows, but the arrows would remain sticking out of the bear. The end result looks more like a purple refrigerator, and the arrows tend not to get "captured" until they've passed entirely through the target, but some of the idea made it through. When an arrow hits the purple thing, its OnCollisionEnter function grabs the arrow's rigidbody and sets it to kinematic, which disables forces, then sets the arrow's transform as a child of the enemy. Instant porcupine effect!

There are unlimited possibilities here, beyond "bair-baiting simulator", and I hope to eventually make this into something more impressive, but I think it stands as a good example of what you can do by stumbling around in Unity for a few hours with a vague idea or two. Time to shelve it and return, slightly refreshed, to the primary project.