Friday, August 31, 2012

New Project Day 1 of 7 Recap

After deciding to do this week long project yesterday, I jumped right in and started getting my hands dirty.  I'm using Unity3d to develop this game, I've been using it for 3 years or so now so I have a pretty good feel for working with it.  I also decided to make this an iOS/Android project.  If you want to ignore this wall of text, there's a movie at the bottom showing my progress.

I spent a bit of time mulling over what type of game to make.  7 days isn't a lot of time, especially when working more or less alone on this project.  I eventually settled on making a puzzle game that focuses on tapping and swiping.  Tapping and swiping are fun gestures to use on your phone, so I figured that would be a good basis to start from.

I started out making a system to lay out a grid of tiles to represent the puzzle pieces.  Once I had a grid layout working, I began working on some basic input so I could tap to select a tile and then tap another tile to force them to flip position.  To add some life to the tile movement, I used Prime31's GoKit Tween Library to animate the translation and scaling of the tiles so they felt more interesting.

Next I started working on the drag selection and line drawing system.  This turned out to be fairly involved to get working, especially the line-drawing part.  I initially tried using Unity's built in line rendering system, but that exhibited some annoying deformation when the line changed direction, resulting in an non-uniform line...ewww


Luckily I came across a blog with some solutions to this particular problem.  I ended up implementing a custom line rendering system using the Unity'd Graphics API, which worked wonderfully.  You can see the results in the movie below.

That's it for the 1st day recap.  Today I'll be working on adding the ability to unselect a tile when dragging, adding some constraints to the drag system, and beginning to create a backend system to track each spot on the board.


Thursday, August 30, 2012

New Short Project Intro...I Guess

Today I decided to make a new game and ideally finish most of the heavy work on it within a week.  To help keep myself honest and on track, I also figured I may as well blog about the experience.  I'm not 100% sure what the game will be, however I'm leaning pretty strongly to doing a simple 2d tile-base puzzle game.  Mechanics for that are relatively simple to create, and there are a lot of cool game variations possible.

Why am I doing this?
My last project Shatter Crash took a little over a year to complete from start to finish.  I still enjoy playing the game and tinkering with it; however working on one project for that long, and as 1 part of a 2 man team, got exhausting.  Doing something short and focused on a tight set of core mechanics will be a breath of fresh air.

What are my goals?
Mainly to have fun and help get myself re-grounded and re-focused.  Finishing off Shatter Crash took a lot of energy and became a grind at the end.  I also want to focus on making something deliberately small in scope and laser focused on a core set of small features.  I tend to feature creep quite a bit, so this is also practice on keeping things small.

Obviously I don't have much to talk about right now as I'm just starting to get things ramped up.  I plan to do at least 1 entry a day to talk about and show off my progress.

Monday, May 21, 2012

Fixing Long Load Times in Shatter Crash

Development on Shatter Crash is moving along pretty well, we are currently working on polishing, UI and bug fixing.  One of the things I decided to tackle today was the long load times we were seeing when traveling from our game play scene back to the main menu scene.  This was especially bad on the iPad's, where we could see load times between 10 and 15 seconds.

The first thing I did was use Unity's cool profiler tool to get a sense of where time was being spent by running the game on my computer. However this ended up failing horribly because the editor continually stalled or crashed while I did deep profiling, probably because the call trees were incredibly deep.  Doing regular, non-deep profiling, didn't flag anything that jumped out as problematic, so I began to suspect the issue had to do with asset loading. As a note, as far as I know Unity's profiler doesn't give much details about asset loading/unloading, so this was simply a theory. (As a note, I didn't have wifi access at the time, so was unable to directly profile the game running on the device.)

I began to suspect the extended load times had to do with our GUI solution forcing Unity to pull in a lot of textures and create a number of object hierarchies.  I tested this by creating an iPad build with most of the UI ripped out to see how much faster the main menu loaded.  To my surprise, it only dropped the load time from ~15 seconds to ~14 seconds...looks like the GUI isn't to blame. I eventually resorted to brute force debugging by removing objects from the scene and pushing a new build to the device to see if things got better.  This certainly wasn't an ideal debug flow, but it did work.

I eventually found the cause of the load time spikes was related to how we referenced the puzzle data for Shatter Crash's game levels.  Our puzzle data is stored in ScriptableObjects for convenience, and each 'level' contains lists with hundreds, or thousands, of entries which define each piece on a puzzle board. For simplicity, I had created a script and prefab which directly referenced each of these puzzle ScriptableObjects (about 30), and this prefab was referenced in the main menu.  Removing the reference to this puzzle container prefab dropped our load times from ~15 to ~3 seconds...sweet problem found!  It seems Unity was taking a long time to load the main menu because it was loading and parsing all the list data in each of the puzzle data files.

Now that I knew the cause of the problem, the fix was fairly straightforward, although a bit tedious.  I changed the puzzle loading system to use Resources.Load to dynamically load the puzzle data we needed on-demand.  I generally shy away from using the Resources.Load() much because it's a real pain in the butt to keep asset paths up-to-date, and when I do I generally write unit tests to validate the existing paths are good.  While I was copy pasting strings, I came up with an idea for a new tool to automatically create Resource paths, hopefully I'll have a chance to create it in the near future

*UPDATE* - The game described here was ultimately released as 'Shatter Crash'.  I edited several places where I referenced it by its old name 'Access Point' to refer to the new name

Friday, April 20, 2012

System.Serializable attribute annoyances in Unity3D



I recently discovered the [System.Serializable] attribute introduces an unfortunate quirk when used in Unity3d, which is very annoying to get around.  When you mark a class as Serializable, Unity will automatically instantiate an object for any field you define of that class type.  Even if you want that field to be null.  Take the following code:

[System.Serializable]
public class SerializableDataClass
{
    public int SomeValue = -1;
}

public class NormalDataClass
{
    public int SomeOtherValue = -1;
}

public class MyMonoBehaviour : MonoBehaviour
{
    // Will Never Be Null, not expected
    public SerializableDataClass DataObj1 = null;

    // Will Remain Null Until Assigned, as expected
    public NormalDataClass DataObj2 = null
}

Logically, you'd expect MyMonoBehaviour's DataObj1 and DataObj2 fields to initialize to null and remain null until assigned an object to reference.  Unfortunately this isn't the case, DataObj1 will automatically have an object created and assigned to it, even if you initialize it to null and try setting it to null in other areas like Awake()/Start()/Update().  This behavior becomes very disruptive if you have logic that triggers based on if DataObj1 != null.

Tuesday, December 20, 2011

Unity3D EditorWindow Formatting Tip

During the past several months I've done a bit of work extending the Unity3D editor to create custom editor functionality for my upcoming game.  Unity makes it ridiculously easy to implement custom functionality in the editor, however their documentation can leave something to be desired.  One of the hidden nuggets I found is EditorGUIUtility.LookLikeControls() , which exposes custom formatting for certain EditorGUILayout elements.




Here's an example of using EditorGUILayout.EnumPopup() and EditorGUILayout.LabelField() to show some enum and string values.  As you can see the description label on the left is cut off, which makes this GUI very unusable.  EditorGUIUtility.LookLikeControls() lets you change the default pixel size of one or both of the content display fields for these methods, so you can make your GUI's much more readable.



Here's the same menu using EditorGUIUtility.LookLikeControls(250), which expands the first content zone to 250 pixels, and provides a nice amount of space to clearly mark the inputs for the menu.  And as you can see at the bottom, calling EditorGUIUtility.LookLikeControls() with no params will restore the GUI system to the default layout for these elements.

Saturday, September 24, 2011

Handling Texture Tiling and Offset in a Unity3d Vertex and Fragment Shader using TRANSFORM_TEX macro

When doing some test work, I found my Cg shader wasn't handling texture offset and tiling properly, resulting in distortion such as below:

The Unity shader on the left properly handles a 3x tiling factor for the texture, while my shader on the right doesn't properly handle the same 3x tiling factor



My shader setup was pretty simple, here's a snippet of the important parts:

#include "UnityCG.cginc"

sampler2D _MainTex;
float4 _Color;

v2f vert ( appdata_base v )
{
    v2f o; 

    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);

    // Texture offset - BAD
    o.uv = v.texcoord;
    return o;
}

half4 frag (v2f i) : COLOR
{    
    return tex2D(_MainTex, i.uv) * _Color;
}

I bolded the problematic part, which is the Texture UV handling in the 'vert' program.  Simply grabbing the v.texcoord will work when there is not tiling or offsets in the texture, but breaks once those elements are introduced

After snooping around, I found the solution is to use the TRANSFORM_TEX macro in the UnityCG.cginc to make sure the texture's offset and tiling are properly applied.  A small caveat to this is you must, "declare float4 properties for each texture before the vertex program, with _ST appended" (Quoted from Unity3d shader docs).

Here's a snippet of my shader with the new changes:

#include "UnityCG.cginc"

sampler2D _MainTex;
float4 _Color;
uniform float4 _MainTex_ST; // Needed for TRANSFORM_TEX(v.texcoord, _MainTex)

v2f vert ( appdata_base v )
{
    v2f o; 

    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);

    // Texture offset - GOOD
    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    return o;
}

half4 frag (v2f i) : COLOR
{    
    return tex2D(_MainTex, i.uv) * _Color;
}

With this happy little change, our shader now properly handles the tiling and offsets of the texture.
 

For those curious, I gleaned this information from the Unity3D Vertex and Fragment Programs and the ancient Unity 2.x Shader Conversion Guide.  The info pulled from the Shader conversion guide regards the _MainTex_ST property needed for TRANSFORM_TEX to work. 

UPDATE - Dec 1, 2013 - The Unity 2.x Shader Conversion Guide seems to have disappeared from the internet.  This information is all still relevant for Unity 4.x release versions