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...