Monday, May 27, 2013

Lerps of Faith


I've been stuck in a test level for weeks - weeks! I finally got something together that I'm willing to live with, but I still don't like it much. The simple-sounding problem was that I needed, in various places, to move an object from point A to point B, in some cases speeding up as it leaves A, in other cases slowing down as it approaches B. Thank Christ I didn't need both at the same time or I'd still be working on it.

Several game development environments support this sort of thing natively with easing functions, but Unity is apparently not among them. Seems like an odd thing to leave out, but the Unity philosophy seems to be that if people want something badly enough, some user will eventually code it up and offer it to everyone else, possibly for a profit, and for this use case one need look no further than iTween, or if one's pockets are empty one could conceivably go to the community and base a solution on something like MathFx.

Granted, there's also the option of hooking my objects up to Unity's animation system, but that felt like using a bazooka on a mosquito, and I'm not sure the kind of easing I want is easy to get to. I had a hunch that I could probably get close enough to what I needed without anything so complex. Turns out I was sort of right, the Lerp function took care of me on the slowing down side, but the speeding up side took a little more head-scratching. Below is what I came up with, you'd attach it to a cube or whatever and then flip the bool to switch between modes.

This was one of those weird little bottleneck problems that is pretty unimportant in the grand scheme of things, but somehow had the power to bring my project to a grinding halt because it felt like it ought to be easy, and not being able to solve it had cascading negative effects on my confidence and motivation. This solution still looks a little weird, but no weirder than anything else in my project, so I'm calling it good.

using UnityEngine;
using System.Collections;

public class test_smoothlerp : MonoBehaviour {

GameObject cube;
Vector3 beginPoint;
Vector3 endPoint;
float startTime;
float tripDist;
float acc;
bool speedUp = true;

void Start () {
cube = GameObject.Find("Cube");
print ("cube = " + cube);


tripDist = 150.0f;

beginPoint = cube.transform.position;
print ("beginPoint = " + beginPoint);
endPoint = new Vector3(cube.transform.position.x + tripDist, cube.transform.position.y,
cube.transform.position.z);
print ("endPoint = " + endPoint);

acc = 0.01f;
}


void Update () {
if(speedUp)
{
//speed up
if (acc < 1.0f)
{
acc += 0.01f;
}
Vector3 nextPos = new Vector3(cube.transform.position.x + (tripDist*acc), 0.0f, 0.0f);
print (nextPos);
if (nextPos.x < endPoint.x)
{
cube.transform.position = Vector3.Lerp(beginPoint, nextPos, Time.time);
}
else
{
print ("done");
}
}
else
{
//slow down
cube.transform.position = Vector3.Lerp(cube.transform.position, endPoint, Time.time);
}
}
}

Sunday, May 5, 2013

Float Downstream



Fear - fear gripped my heart in its clammy fist. After making a new WebPlayer build to replace the somewhat outdated one on my webpage, I fired it up and found that it didn't work. I realized I hadn't tried playing the game in an external build for quite some time. The game worked when played in the Unity Editor's play mode, and that should just be exactly the same as a built version, right? RIGHT??

The game's main menu and auxiliary screens seemed to work fine, but when starting a new game, the player would be stuck at the character input screen, as no amount of clicking would actually select a character and launch the first level. This worked perfectly fine in the editor. The setup is, a UI script that lives on the Main Camera in this scene Instantiates all three of the player prefabs at positions based on the screen size, and hangs a scipt called UI_dummyPlayer on each of them. That script just has an OnMouseDown event that fires whenever someone clicks on the GameObject that the script lives on, loading the next level with the appropriate character as the player.

A platform inconsistency is by nature a painful problem. I started looking for diagnostic tools. The first was the fact that you can right-click on your game in the WebPlayer and bring up a crude development console, pictured above, which in my case read

MethodAccessException: Attempt to access a private/protected method failed.

and helpfully pointed me to the very function causing the problem. The two potential culprits in there are the DontDestroyOnLoad call and my XML Serialization stuff... I started to get a sinking feeling. I quickly narrowed the problem down to these two lines:

seattle = City.Load(Path.Combine(Application.dataPath, "City.xml"));
seattle.Save(Path.Combine(Application.dataPath, "seattle.xml"));


and with some searching online I started to piece things together. Unity's WebPlayer has some built in security features that stop you from reaching into code that is stored in certain ways. I did a quick test on Path.Combine alone, as I hadn't used that before either, but the WebPlayer was fine with it. It was balking at my City.Load function, which I talked about in a previous post. It's another case of using some code I don't understand well, but I understand well enough that the WebPlayer is blocking me from access to the game's underlying file structure, which would most likely disallow things like

using (var stream = new FileStream(path, FileMode.Open))

and there are plenty of threads online about this and they all die out pretty quickly when a senior user steps in to say No, you can't do this in WebPlayer, it would in fact be a glaringly dangerous security flaw if you could.

One post suggested a potential solution: if I stored my xml files in the same directory as my game on the website, I could use Unity's WWW functions to read that xml into a Unity object without touching the internal filesystem. The effect would be the same. Unfortunately, the example code for this employed XmlReader, where I was using XmlSerializer. Also, the process outlined involved junking all of my Xml code, and one of the other posts I read seemed pretty confident that I could still use the XmlSerializer class from within WebPlayer. If the FileStream was indeed the problem I might be able to keep most of my code.

The breakthrough finally came as a result of this postwhere the suggestion was to use XmlSerializer in connection with Resources.Load and something called a TextAsset to bypass use of the prohibited FileStream class. Other exotic tools in play include MemoryStream and Encoding.UTF8 ... we're somehow simulating a streaming file operation within the game's runtime memory, which I find baffling and kind of magical. We have replaced this:

var serializer = new XmlSerializer(typeof(City));
using (var stream = new FileStream(path, FileMode.Open))
{
  return serializer.Deserialize(stream) as City;
  stream.Close();
}

with this:

City loadedCity = null;
TextAsset myAsset = (TextAsset)Resources.Load(fileName, typeof(TextAsset));
byte[] bytes = Encoding.UTF8.GetBytes(myAsset.text);
using (MemoryStream stream = new MemoryStream(bytes))
{
  loadedCity = (City)(new XmlSerializer(typeof(City))).Deserialize(stream);
}
return loadedCity;


and lo and behold, the version built for the webplayer runs without error, characters are selectable, xml is deserializable, the sun is shining, and all is right with the world. I'm taking the rest of the day off.

Thursday, May 2, 2013

Orange You Happy Now



Everything was going fine until I hit the color orange.

A little background here. In order to complete a level, the player needs to pick up five bus passes. Each bus pass has associated with it two particle effects, one a rising stream of particles for the at-rest state, as pictured above, and one a sort of blooming effect on the player when the thing is picked up. Both of these are the same color as the bus pass.

The particle systems are attached to GameObjects which are then stored as prefabs. The bus pass itself is placed in the scene view with a pickup script on it, and I toggle which color this particular pass will be via the Inspector, as the list of bus pass colors is an enum within that script. When the game starts and the bus pass script runs, it looks at that variable to find out what color it ought to be, then switches to the appropriate frame of its' RagePixel sprite. Each bus pass uses the same sprite, which just has five frames of the same image in different colors.

I made the ambient particles first, and I just set the color of each directly in the particle system before making the prefab, so I ended up with five different ones like "prefab_particle_buspass_orange" and "prefab_particle_buspass_green". Each prefab was assigned to its corresponding bus pass through an inspector variable, and each pass Instantiated that prefab during its Start function. Doing it that way once was, I felt, an acceptable level of laziness, but when it came time to do the bloom effect, I decided I had better just make one, "prefab_particle_buspass_pickup_any", and then programatically change the color. After all, each bus pass knew its own color, so it should be easy enough to use a blank white material and just throw RGB colors at it at runtime.

My first "huh" moment was getting the message "UnityEngine.Color does not contain a definition for 'purple'." I must be spoiled by Unity's easy access to so many MSDN libraries, but I figured a robust suite of crayola colors in the API would be more or less de rigueur. Not the case this time, but no big deal. Since I'm using C# and Color is a Struct like Vector3, I have to remember to replace

Color purple(128.0f, 0.0f, 128.0f, 1.0f);

with

Color purple = new Color(128.0f, 0.0f, 128.0f, 1.0f);

but again, all is well, and my purple looks purple in-game! Well, a little pink but whatever. Let's try a classic Cadmium Orange:

Color orange = new Color(255.0f, 97.0f, 3.0f, 1.0f);

This comes out yellow.
Undeniably, unsquint-at-ably, absolutely damned yellow.
I thought for a while, and I spent maybe a bit too much time at Wikipedia's unusually fascinating page for the color orangeand I thought some more, and eventually I did the right thing, which is to resort to googling ever more plaintive rephrasings of one's problem and clicking on Unity Answers links until something gives.

...No, I'm kidding, the right thing to do is check the documentation, which in my case would have easily shown this, for example:

Yellow. RGBA is (1, 0.92, 0.016, 1), but the color is nice to look at!

Unity doesn't use RGBA values of 0-255, it uses normalized values of 0-1. Maybe that's a Scandanavian thing? I do like the consistency of it, Alpha is usually going to be 0-1 anyway... I tried to learn a bit more about this but I soon wandered into a forbidding land of shadows and had to turn back. Not tryng to be incurious here, but your basic safety orange should not require post-graduate math.

Unfortunately my "what if this works" first stab of just dividing each of the values by 255.0f gives us roughly

Color orange = new Color(1.0f, 0.3803f, 0.5019f, 1.0f);

Which renders onscreen as a sort of ill salmon color. Then suddenly, in the next tab, a light shone upon me, for the good people of Unity had, by their own divine providence, thought to include a built-in function to do this exact thing.

Moments later I had

Color orange  = new Color32(255, 97, 3, 255);

Which pops out blazing orange. I believe it was Ben Franklin who said, "I only try to understand something complicated until I figure out something simpler that will allow me to stop trying to understand the more complicated thing." As for the mystery of why my totally wrong purple was somehow sort of purple, I guess if you overflow the bounds of whatever kind of structure Color is, it just holds the max value, like a cup of coffee being filled by someone who has fallen asleep. (128, 0, 128, 1) is to Unity the same as (1, 0, 1, 1), which is Magenta, which looks sort of like purple, in a certain light.

Sunday, April 14, 2013

T



I wanted to get a little deeper into some methods for storing and retrieving information. With some research, I found that in CS terms I was thinking about data structures, so I hopped on my favorite internet book ordering behemoth and in a few days I had a copy of Ron Penton's Data Structures for Game Programmers. It comes highly recommended from folks at work, some of whom are even thanked in the front pages, so I know I'm on the right track with this one.

One tiny concern was that the book's examples are in C++, while I'm working with Unity in C#. Well, how big a deal could it be? I'll just re-write the example code and Bob's your uncle. It took me about a dozen pages to get in trouble.

Ron wants you to be sure and understand a few things up front. The first is big-O algorithm complexity analysis (which I'll tackle in another post .. someday) and the other is templates. These are functionally equivalent to C#'s generics, right? No problem. The first example I tried to port over was a C++ function for adding either floats or ints together, depending on which was passed in. Well, it turns out in C#, things like this

public T  Sum<T>( T p1,  T p2) 
 {
     T sum;
     temp = p1 + p2;
     return sum; 
 } 

just straight up don't work. Why not? further research led me to an interview with lead C# architect Anders Hejlsberg, who I will quote on this very topic:
"...in C# generics, we guarantee that any operation you do on a type parameter will succeed. C++ is the opposite. In C++, you can do anything you damn well please on a variable of a type parameter type. But then once you instantiate it, it may not work, and you'll get some cryptic error messages. For example, if you have a type parameter T, and variables x and y of type T, and you say x + y, well you had better have an operator+ defined for + of two Ts, or you'll get some cryptic error message. So in a sense, C++ templates are actually untyped, or loosely typed. Whereas C# generics are strongly typed."
Undaunted (the book is big and wasn't cheap), I dove further online, turning up a set of C# files called the Miscellaneous Utility Libraryput together by a Google engineer named Jon Skeet. He and Marc Gravell (one of the Stack Overflow guys) put together this solution for doing what they call "maths" on their side of the pond in the context of generic classes in C#. A small download and a using statement later, I was stuck again, as the Unity compiler didn't want to recognize the construction Operator<T>, for reasons that still hover slightly beyond my understanding. 

The MiscUtil pages reference an article by one RĂ¼diger Klaehn, a "freelance developer in the space industry", which sounds like the coolest job ever. He articulates the problem succinctly:
"To constrain type parameters in C#/.NET, you specify interfaces that the type has to implement. The problem is that interfaces may not contain any static methods, and operator methods are static methods."
RĂ¼diger presents two solutions, one of which I sort of understand and the other, which is far more performative, I don't understand at all. Fortunately I doubt I'll need to use so many numerical generics every frame to cause a slowdown in Unity (how many would that take I wonder) so I felt confident going with the first option. 

I was mildly dumbstruck by the idea that you could just declare a function without a body like this:

public abstract T Add(T a, T b);

as long as it's something abstract that you plan to override. I was even more nonplussed by the idea that I could use

namespace Int32
{
//custom calculation function
}

to just reach into the guts of how Unity deals with basic numbers, and just scribble in the margins as it were. That's really cool. Finally, when I got to the following, my brain broke:

public class CalcMethods<T> where T: new()
{
//a generic adding method + whatever else you need
}


I've seen cases of putting code in a function definition, with what they call a lambda, and I suspect this is something similar, but it's still blowing my mind.

In any event, I now have a function that takes a List of either floats or ints, and adds them together, and its easily extensible to whatever other kinds of numbers might come up, so I guess I'm ready to continue. At this rate my side-quest through this data structures book will probably take about a decade. Better brew another pot.



Friday, April 12, 2013

Eat Your Serial



Starting in on the process of making Level Two is a big wrenching moment, kind of like seeing my 2D game in perspective view. It becomes obvious how much is assumed, hardcoded, made of magic numbers. Wires must be pulled out. Questions as simple as "where does the player start" might have different numerical answers for each level. This is one of the most common questions on public game dev forums: "I have a bunch of information I need to put in the game, like a long list of magic spells with all their damage and cooldown numbers, how do I represent it?" In my case it's a fairly small list of things like the scene's loadable path, where the bus should pause to pick the player up, etc. but the principle is the same. The actual process I still don't really get, it's mostly cribbed from a few different tutorials, who have a few implementation bits in common but diverge otherwise.

I used an XML file and the System.Xml.Serialization namespace. One of the funny things about Unity is that as often as not when I'm leveraging its powers to do something I'm actually just leveraging the standard MSDN libraries, which hey, System.Xml has more things you can do with an XML file than I'll ever want or need, so why reinvent the wheel? Like I said, the tutorials I checked all have their own take. There's always an XmlSerializer and a FileStream, but sometimes there's an XmlTextReader (which I didn't end up needing), sometimes an XmlNodeList is employed (didn't use that either), but the end result is what matters, and what I got works. Also kind of cool that I have to use stream.Close() because I'm in one of the few corners of C# where memory isn't fully managed. It's like, retro vintage, man! The only annoying bit is that classes that are derived from UnityEngine.Object do not appear to be serializable, so if you need to pull something like a Vector3 you're stuck hacking in translation functions that will grab three float nodes and smoosh them together or something equally ugly.

I'm really grappling with the metadata syntax as well, and I'm getting a mental picture of them as sort of magnets that allow you to attach properties in your program to external data that may change outside the scope of the program in ways you don't want to worry about. Probably not exact, but a good enough image for now.

The sudden possibility of storing and using large amounts of easily tweaked data is of course leading me to all sorts of other ideas, but no, for now we will stick to the plan and the schedule. Last sprint wrapped, a few things got punted. Inevitable.

I am starting to understand enough coding to sometimes sense that I am making a poor decision, although not enough to understand what the preferable course might be. My options / death / audio menu is a flying carpet made out of GuiLayout.BeginArea and transform.position.y, where I'm doing a three-way switch in the Update() to decide which of three sets of (crudely laid out) text buttons to show. I've always had trouble with "layout languages" like CSS, or basically anytime I have to think in interconnected scaling squares with various interdependent attributes ... makes my head hurt. I've hacked it up enough to work, but I don't know, I might return to it.

Mostly though it's been sweeping up stuff like the transitions from one level phase to another - making sure we don't let the player move and shoot when the level end animation is playing, stopping some bugs where bullets got huge and lived forever, trying slightly to improve the art, various little tweaks.

It's going to be that way for a while, I'm looking down the list and it's a lot of menu this and the skeleton dies wrong that, and move the camera when you do the other thing. It's the long bleak desert of the real, Neo, it's game development.

No, once I get the structure set up to slip between levels I can plow through the art and design for the other neighborhoods and that will be a lot of fun. I just need to work a little faster...

Monday, March 25, 2013

Back in the Triple Digits



Just truckin through my backlog, on my way to full vertical slice, and not that far off either. The shooting and jumping aren't exactly ... inspiring, but at least they work. I spent a lot of time fooling with gravity when I was making the floor and platform tiles, trying to find that right scale for the "running jump" mechanic. The way I wanted it to work, you could complete the level just walking, like if you didn't ever realize holding the fire button makes you go faster (I do change the animation, I tried to make it obvious), you should be able to get all five bus transfers just by jumping normally, although you'd have to take some circuitous routes and it would be a pain in the ass. At the same time the running jump couldn't be too powerful, or since the platforms are so close together you get this queasy thing where the player just jumps toward the side of a platform, slides up, and ends up standing on top, which isn't very jump-like. I tried adding a RigidBody component for physics jumps in the hopes of getting something springier, but the intersection of the RigidBody and character controller was causing some Exorcist-like behavior so I bailed on that one. I'm not thrilled with where it's at now, but I can live with it a while longer.

Anything the player can touch is a primitive 32x32 cube displayng a frame (via a scaled and offset material) of one of two 256x256 tile sheets. The buildings and clouds are big textures (the clouds are 4096 wide) painted on scaled up quads, and scripted to move in parallax to the player. Most of the collision volumes are cubes the size of the tiles, but platforms have scaled down collision boxes, as do some of the objects. I'm still using the old pickups but I'll probably make them tiles too eventually. The frame rate hangs reliably in the triple digits. This concludes, knock on wood, the technical implementation of the guts of the game. The rest is window dressing, oh and design.

I re-learned some things about instantiating and destroyng prefabs. I spent a little too much time re-learning that a switch/case runs on break; statements and yes, they mean it, and any code you had in that function below the switch/case is not getting run, which is probably why it is not as effective as you thought it would be. At least, I think that's what happened ... regardless, it works now. I re-learned that your first level design instincts are often too big. This level is actually pretty small for a platformer now, but only because I wanted everything to feel closer together. In a sense all the objects really are kind of tetris-jammed together, but it's really the same set of elements from the larger draft of the level, just brought in tighter, I think I only deleted like two objects. It's odd that I got a lot of stuff right the first time but I got the scale totally wrong.

The actual design of the level, given the constraints imposed by the grid, the jump tuning, and the five bus passes (plus a bus stop), was dirt simple. Figure out how to make a bus pass hard to get to, then do four variations. One is on a catwalk, another is tucked behind a roving skeleton, one is in a corner. None require run jumps but all are made easier by run jumps, run jump is frankly a little OP right now but it feels better than it did. I even started to polish a little by adding particle effects to the bus passes, but of course now I'll need particle effects for everything...


Next is the level-end bus-pickup "experience", the fail/restart, maybe some options geegaws, and another say three levels, all built with similarly small tilesets, maybe one extra enemy per level and that's about it. With my schedule the end is still months away, but I can see it, coming ever more clearly into focus. Gotta get this puppy out the door!

Tuesday, March 12, 2013

Performance Anxiety



What little rationale there was behind building a 2D tile-bsed platformer in Unity went something like this: learn the tools and workflow on something small enough where you won't have to worry about optimizing for performance. This was naive.

The tile map implementation I described previously involves painting tiles in the scene view, each tile consisting of a textured mesh. When I picked my head up from my second layout of the opening level (wonder what number that will get up to) and pressed Play, Unity thought for awhile. Twenty-one seconds, to be exact. My gameplay and scenery grids combined were holding 8087 tiles, each of which contained a single quad.

Many things were vexing about this. For one, the stats window showed 384 verts comprising 192 triangles, which didn't seem like all that many to me. For another there was the fact that after that twenty second startup, Unity seemed pleased enough to hum along at a triple-digit FPS while the playfield was traversed; there was no in-game performance hit. Without a deeper understanding, or the CPU/memory profiler Unity offers for a mere fifteen hundred bucks (along with a Pro license), there was little I could do but conclude that I was just Loading Too Many Things.

Idea #1: "Well, how many is too many?"


My Test mind kicked in. I wanted to repro the issue, isolate it from its context. I made the scene shown above, with a total of 10180 red cubes, boasting 104,800 vertices making 52,400 triangles. The whole thing loads in less than three seconds. OK, interesting. Apparently 8087 tiles is not too many. What else is going on?

Idea#2: "It's the materials."


I was doing what I thought was a really swell thing by confining my entire city scene to one 256 x 256 texture made of tiles, which were arranged for display, uv-wise, by a material unique to each tile. Maybe that's bad? Really grasping here, not even mentioning stuff I thought of before the red cubes, like stitching all the meshes together at runtime (possible, but goodbye texture data and anyways I tested it and that would happen in script after my startup problem is already come and gone, so who cares?).


Anyway the point is I was desperate for a simple answer. I decoupled all the materials from all the prefabs, turning everything in the level pink. My start time somehow went up to 24 seconds.

Idea #3: "It's a script"


Since this was a one-time perf hit at startup, perhaps one of the scripts was looping over the tiles at startup in some poorly thought out way. I feel like I would have noticed that earlier than I did? Whatever though. Let's comment everything out. 24 seconds.

Idea #4: "Uhh maybe ... the tile editor's Instantiation method, isn't that deprecated?"


Ugh fine whatever. Let's rebuild the level from scratch, with the same tools, and figure out where and when the perf hit starts to happen. OK looks like when we get over about a thousand of these we start to bog down. With the new version of Instantiate, and without materials. These objects are piling up at around 1000, and the cubes were loading like butter into the quintuple digits.

Idea #5: "Something about a mesh as opposed to a cube?"


Turned off shadows. Tried a cube. Tried a sphere. 


PrefabUtility.InstantiatePrefeab and it's deprecated Editor cousin allow you to do things like paint in scene view, you're painting with prefab instances, so it's hard for me to conceptualize that you would need to Instantiate all those again at runtime, because I already did that, I'm looking at them, they're right there, but I guess what I'm looking at could be a preview of some kind. It would make sense that it would take some time and resources to bring all those cubes into being, and that's really the only thing left that seperates that tower of cubes from my level: the cubes aren't prefab instances.  

That points me toward really dreadful things like asynchronous level loading (another pro feature), and eventually I arrive at

Idea #5: "I guess we'll have to find a way to render a level without loading thousands of tiles"


I guess you could, you know, use a hundred or so tiles for sidewalks and platforms, then just draw some backgrounds and put them on big quads. Rather than, you know, making a skyscraper out of hundreds of individual meshes, each uv mapped to part of a single small texture, a "solution" that somehow joins the worst aspects of all possible approaches. I was so close, though! Throw that texture in and just paint the level, so convenient! Wait, hold on, if prefabs are the problem, why not

Idea #6: Alter the editor window script to stop instantiating prefabs and instead make meshes from scratch with the appropriate materials on them!


Oh lord. All right, worth a shot. Redid the tileMap code to make a primitive again, like the demo script, instead of instantiating. Used cubes as Unity has no Quad primitve type. Rotated the cubes. Updated the custom editor to paint materials instead of prefabs. Applied a variety of textures to simulate what I'm actually doing in the level.


Bam. 7956 cubes. Feels like between three and four seconds. Now, though, even that length of load feels kind of intolerable. Eh, I think if I do the buildings as scaled-up single quads and leave the tiles for the floor and platforms I'll be OK, shouldn't be more than a second. The lesson, as far as I can tell is: prefabs are slow. That is, unless after my third buildout of the level I find out the problem is actually something else...