Pages

Thursday, January 9, 2014

Wrapping Up 2013

Version 0.5 Released:

With
the various family and friends commitments of Christmas and New Years and, just for fun, a nasty flu bug knocking me out for almost a week, development continues to be a bit slow... Not that I'm complaining about the holiday gatherings; they were fantastic (not so much the flu bug). Delays be damned, I feel that I've finally pieced enough together to
warrant a new release and blog update.

Just comparing this release with the previous one, I'm amazed at what a difference a bit of polish can make. Here's hoping you guys agree!

Major Changes in v0.5:

Stat Tracking:

As promised last release, high scores will be reset with this release. Expect further resets in future releases... don't become attached to them ;-)

In-Game Graphic Improvements:

New shader/material rendering to give the game more of a cartoony feel

When selected, gumballs now animate to identify their selection instead of going partly transparent

More 'juiceness' in the form of revamped gumball EXPLOSIONS, bonus announcements and background (say goodbye to the black background!)

User Interface Improvements:

Complete revamp of the UI look. Hopefully, the game has a bit more personality now!

Say hello to Frank, the rabbit. He needs your help picking up these gumballs!

Dedicated game summary screen created

Initial Help / Intro screens added to explain (probably poorly) to the player how to play

Further modularization of the interface to make updates even easier

Sound Effects:

Selection sounds now use a 'major scale' to make it sound a bit happier

Each color gumball has its own scale of tones

Music now accompanies you as you play the game

NOTE: There is currently no way to disable sounds. This will happen in a future release

Game Play and Internal Logic:

[BUG FIX] Any chain you're in the middle of making when the game ends will be added to your final score

Refactored how internal logic determines if gumballs match for more accuracy and efficiency

This Period's Highlights:

Early Feedback Continues to Focus Development:

As always, the
latest player feedback continues to be quite useful. Reddit continues to be the
most popular source for Feedback. Most feedback comes from posts in
/r/unity, /r/unity3d, /r/indiecode or /r/gamedev's Feedback Friday and
it's always enlightening. This go round, most folks were asking for
'cooler effects and explosions.' Well, it's time to turn gussy up this puppy... at least as much as this non-artist can ;-)

But first...

Getting Learned in C#:

In previous posts, I've mentioned that I'm rather new to C#. As a result, I'm learning about cool new (to me) features all the time. Today's feature: System.Linq. If you've never heard of it, go do an Internet search for the MSDN entries for it. Then go read this (Unity3D related) blog article. If you can't see the potential awesomeness in the library, then go back and look again. I won't reiterate what can be read elsewhere, but, suffice to say, Linq is like having access to bit of SQL-query goodness in any of your C# collections (arrays, lists, dictionaries, etc.). Creating unions, differences, and many other random queries are rather trivial to code. The tradeoff is, so I've been lead to believe, that, it's not the most efficient of libraries... so, don't go Linq crazy in your update loops!

So, how am I using Linq? Well, there are various pieces of my codebase I'll likely revisit to refactor to take advantage of Linq, but, initially I'm using it in my new 'AI' logic. Ok, AI is probably waaaay overselling what I've done. One of the pieces of feedback I've received was from a person wishing that the game would highlight suggested moves if the player has been stuck for a while. Good idea. Now how to do it? I ultimately decided to take a snapshot of the positions of all the gumballs and reuse the same selection logic that the player uses to determine where every potential chain is. This ultimately amounts to picking a gumball, finding 'close' neighbors, identifying if the neighbors are the same type of gumball, then, if they are, adding them to a list... you then repeat the process with the newly added neighbors. In the end I ended up with several lists that needed to be joined together. A simple List1.Union(List2) logic is all that's needed to get the job done. Could I write my own logic to join arbitrary lists together? Sure. But, why do that? Better to reuse existing libraries, I say!

So, that's you're C# knowledge dump of the moment. I'm sure anyone who's familiar with C# could spout off all sorts of other great benefits of Linq (as well as other libraries I don't even know about). If you have something cool to share with a C# noob, drop me a line in the comments. I'd love to learn!

Bring on the Personality:

Games, as well as people, are typically perceived as 'better' if they have some personality. Ask yourself, what's more fun, a potato or a Mr. Potato Head? (if you answered 'potato,' go build be a potato-powered clock, smart guy!). Potato Head wins. He has a face and some arms and feet. He's a bit more personable than your standard spud.

I learned a bit from Mr. P. Head. GumBall Fall now has its very own personality in the form of Frank, the rabbit and a bit of a (lame) back story as to why the player is collecting gum balls. Am I happy with what I have? Yes and no. I feel that by just adding the few things I did, the game is 100% more friendly for the player. But, there's definitely a heck of a lot more I can likely do to make great improvements. But, everyone has to start somewhere, right? I'm starting with a bunny named Frank!

Damn You, Draw Call Batching:

So, the majority of refinements I've made for this release aren't really worth writing in detail about. Graphics look prettier, there are a few new screens, etc. Nothing mind blowing. However, I want to take a minute and write about Draw Call Batching and it's relationship to Unity3D. Every object in my game needs to be drawn. The inefficient way to do this is to simply have a draw call for every item in the scene (assuming its on camera). Unity3D will attempt to dynamically batch draw calls. If you have a bunch of objects that share the same material (basically the texture/shader combo used to render the object), Unity3D will draw all those objects in one call as opposed to one call per item. Needless to say, that's much more efficient.

My game ought to be able to take full advantage of this batching. 99% of it is simply 6 different types of gumballs... and, each gumball uses the same material, I simply just change it's color. So, 48 gumballs ought to be reduced from 48 calls to 1 call, right? Not so much. When a gumball is created or re-pooled for later use, it was dynamically getting assigned a new color (i.e. a property in its material was being altered). Turns out, altering a material's property creates a unique instance of the material. Thus, when my game initially creates my 48 gumballs, they all are using the exact same material... and one draw call is used. But, the second I change a gumball's color, a new material is created. Thus, 48 changed gumball colors, 48 new materials. 48 draw calls. Booooo!

I figured the solution was simple. Just create 6 unique materials: One for each gumball type. Each gumball type will now share a single material. 6 materials, 6 draw calls. Not quite the 1 draw call I figured I might be able to get, but certainly a lot less than the 48 calls I was actually making!

So, I made the change and re-ran the game looking for those 6 draw calls... I'm still getting 48!?!? #*&@##@&*$!!!! Time for more Internet digging! Turns out, materials are only part of the problem. The other part is that, due to efficiency considerations, Unity3D will only dynamically batch draw calls on objects that contain less than 900 vertices (or fewer depending on what UV, Normal, etc. mapping you're using in your material). The sphere meshes that come with Unity3D contain close to 500 vertexes and I'm using some UV info which, after doing some experimenting meant that my gumballs could only have around 300 vertices . Ugh! This meant that I needed to create myself some new simple spheres and led me to boot up my copy of Blender (which I know VERY little about) to create a more basic sphere. After stumbling around in Blender for a bit, I finally created a sphere with around 270 vertices.

With the new material system and the new low-vertex spheres, I finally had some gumballs that would batch! My draw calls dropped from 48 to 6... BooYah!

So, who cares? 48 calls really doesn't seem like that many, right? Well, on the PC, no. I never noticed any performance issues. Even when testing on my Galaxy S3, I saw rock solid 60fps frame rates. However, running the game on my 2012 Nexus 7 showed that I was averaging 35fps. That's still pretty decent. But, my game's really not all that complicated or graphically intensive. Why should I give up 25fps for no good reason? After successfully batching my draw calls, the frames per second on my Nexus 7 shot back up to a rock solid 60fps.

What's the moral of all of this? Keep an eye on those draw calls! In the mobile world, even a few extra can drastically affect your performance. Because, not only was my frame rate dropping, but, the CPU/GPU was working 8x harder per frame for no good reason... that's going to just drain a mobile device's battery faster than it ought to.

There's definitely more to Unity3D's draw call batching than I've discussed here (both dynamic batching and static batching that I didn't even touch on since it's only available in Unity3D Pro). Check out the Official Documentation for more information.

Tool Shout Out:

Just wanted to take a moment to give some proper recognition to a free tool I've just recently started using. I've mentioned Unity3D and some of the major libraries I've been using, but, one needs pretty visuals and sounds to go with any game. Today's shout out goes to Inkscape.

Are you familiar with Adobe Illustrator? I knew of it in name only. Well, Inkscape is apparently a pretty dang similar free/open source competitor. So, what is it? It's a vector graphics art tool. Frank, the bunny in my game, was made using vector graphics. I can't take credit for his initial creation (that credit goes to some free-to-use vector character art) but, thanks to Inkscape, this non-artist was able to tweak him to look less sinister and more goofy.

Before and after shots of Frank:

That's all for this post. Thanks for reading and (late) HAPPY NEW YEAR!