• Register

Gamieon is a privately owned entertainment software development company located in Tampa, Florida. Since October of 2004, we have aimed to provide quality video game software which emphasizes both intellectual and action-driven challenge to the gaming community. Gamieon depends on the talent of individuals working as a team to develop video games and video game engines with a focus on exceptional game play and surrealism.

Blog RSS Feed Report abuse Skillz iOS, Unity 3, and I

0 comments by Gamieon on Feb 24th, 2014

In December 2013 I entered into a small "venture" with the Skillz team to make a simple game called Tiltz Tournament where players could compete for game coins or real money. I developed the core game, and they provided the tools for matchmaking and account management. Here I write about my experiences in hopes other Skillz developers can benefit, find solutions to issues, and avoid the mistakes I made. This entry is laid out in six parts:

  • Getting the Unity project set up for Skillz
  • Getting the XCode project set up for Skillz
  • Setting up Parameters and Tournaments on the Developer Portal
  • Completing the Skillz integration in Unity
  • Completing the Skillz Integration in XCode
  • Testing production mode

If you're the impatient type like I am, just go to QUICK BUILDING REFERENCE to see how to build a Skillz-enabled game for your iPhone.

Getting the Unity project set up for Skillz

After the core game was created in Unity 3 and tested on my iPhone, I followed the instructions on the Skillz homepage to integrate their SDK into the Unity side of the game. Upon trying to import the Unity package, Unity crashed. This was because the package I got was exported from Unity 4 and is not compatible with Unity 3. My project would no longer open in Unity 3. I fixed it by doing the following:

1. Going into Finder and deleting the SkillzDelegate prefab from the project's folder.
2. Starting Unity
3. Making my own Skillz prefab by:

A. Making a new empty game object
B. Adding the Skillz and SkillzDelegate scripts to it.
C. In my Unity Project tab, click on Create, select Prefab.
D. Drag and drop the game object to the prefab.

Before continuing the integration, I wanted to make sure I could still build the project and deploy it to my iPhone. Since Skillz requires iOS 7, I had to go into my Unity project settings and make sure I maxed out my iOS version settings. Unity's deployment target only went up to 6.1, so I had to change the app deployment target to 7 from XCode later on. I also had to make sure my project was set up for iPhone only. I then proceeded to build the project from Unity so it would generate the XCode project.


Getting the XCode project set up for Skillz

XCode didn't open automatically because Unity 3 doesn't know how. Still, the iPhone assets were created, and I was good to move forward.

The first thing that tripped me up in XCode was that the deployment target (at the top left next to the Play and Stop buttons) was set to the simulator, so I got a bunch of build errors. I plugged in my iPhone 4 and made sure the deployment target was my iPhone.

I went to the General tab of the project, made sure the deployment target was iOS 7, and that the Device Orientation was only Portrait. Scrolling down further I noticed that some app icons were missing. Again, Unity 3 didn't know to put them there. I had to generate icons in the missing dimensions using The Gimp, and import them into my XCode project folder. Then I assigned them to the icons in the General tab.

I then followed Skillz' instructions to integrate their SDK into the XCode project.

After that, I tried building using the Command-B button. I got several linker errors indicating the std library was missing, and some Game Center-related functions were missing. A little puzzling, but I found the solutions. Under the Build Settings tab, I selected (All) and (Combined) at the top. Then I scrolled to the section called "Apple LLVM 5.0 - Language - C++." There was an entry for "C++ Standard Library." I set it to "libstdc++" and that fixed the std linker errors. After that, I went to the Capabilities section and turned on Game Center (it is bound to my Apple account so you may not have this problem).

I then attempted to build the app again, and it succeeded. I was then able to deploy it to my iPhone 4. Of course I did not actually invoke Skillz functionality in the project, so the app behaved just as it did before.

At the top of the screen was the pesky status bar (battery life, time, etc.). I made it go away in subsequent builds by going to info.plist, adding "View controller-based status bar" and setting it to NO.


Setting up Parameters and Tournaments on the Developer Portal

The next step was to set up the tournaments on the Skillz developer portal. My journey began on the page where I had to enter Parameters. It took me a while to realize that the Parameter list was a collection of every possible unique property of a game for any tournament, and the Parameter list values are the DEFAULT values that the tournament-specific parameters get populated with on the developer portal in the next page. In my game, the Parameters which defined a unique game were the duration of the game and the existence of obstacles. So on my developer portal, Tiltz Tournament has a grand total of two parameters called "TimeLimit" and "Obstacles". TimeLimit has no whitespace because I got errors trying to fetch "Time Limit" from the parameter dictionary from Skillz, and decided I didn't want to deal with it. The value of "Obstacles" is "On" because most tournaments have them turned on. The value of "TimeLimit" is "90" for the same reason.

As for the Tournament list, I could not add or remove entries. I could only change existing ones. Furthermore, the entry fee and player counts seem to be linked. I'm cool with that. I also decided I didn't need more tournaments than they had existing; having more than eight would be overwhelming to the player I think. I ended up using 5 tournament slots for myself, and renaming the other 3 tournaments to N/A so the Skillz team knew not to include them. One of the N/A tournaments was a special developer tournament where I made "TimeLimit" a value of 5. This enabled me to test the game ending due to the clock running out without having to wait 90 seconds.

By the way, after you fill out the Parameters and Tournament List, you go into sandbox mode automatically. Another important bit: You can ALWAYS GO BACK AND CHANGE YOUR TOURNAMENTS, PARAMETERS, AND MOST ANYTHING ELSE. I find that to be a particularly helpful facet of the Skillz developer portal.

Completing the Skillz integration in Unity

What threw me off the most was not understanding the flow that Skillz had intended for the game. The flow is basically this:

  1. Main Menu
  2. Skillz Interface - Game selection / matchmaking
  3. Game
  4. Skillz Interface - Game completion
  5. Skillz Interface - Game selection / matchmaking
  6. Game
  7. (repeat 4-6)
  8. Main Menu

The main menu is the launch point for a continuous back-and-forth between your game and Skillz. If a player quits from Skillz, only then should they be taken back to your main menu.

As I implemented the Skillz functionality into my game, I learned that the Skillz package doesn't seem to like Unity calling Application.LoadLevel from a Skillz callback; at least in Unity 3. When you write your game in Unity 3, you should make sure you have a reset function in one of your scene components so that you can effectively "reload" the scene without actually reloading it. Even if it doesn't crash for you like it did for me, you save yourself the time of reloading all the scene assets. Be sure that your reset function also pauses the music.

One thing I was not a fan of were the developer TODO comments in the Skillz scripts where I had to write my own code. This is because if I download a new package, I could overwrite their old scripts and therefore my changes to them. I wrote my own static class with functions to be called from Skillz's callbacks to minimize any pain of re-importing their scripts.

Completing the Skillz Integration in XCode

After finishing the Skillz integration on the Unity side, I was ready to take a test drive in sandbox mode on my iPhone. After building and running it, and learning the lessons that I wrote about above, I was able to get it working smoothly with two exceptions.

First, there was a bug where if you tilt your iPhone in a way ideal for landscape, and you quit the game, the Skillz interface would get all glitchy and messed up looking. I fixed this by opening Classes/AppController.mm, going to the function

(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *window)

and commenting out the landscape enumerations so that they were not included in the return value.

Secondly, I noticed my app icon was missing from the Skillz interface next to the "Go back to " button. I never did figure out how to fix that.

Testing production mode

Now it was almost time to make the release. I turned off sandbox mode, uploaded an App Store-provisioned .ipa file to my Skillz developer portal, clicked the Sync button on the Skillz developer portal, then clicked on the Play button in XCode to build and deploy it to my iPhone. I kept getting this error when going into Skillz: "Sign Up Error - Invalid client serv request." After going back and forth with the Skillz team, I figured out that the problem was the manner in which I installed the app onto my phone. I fixed it by deleting the app from my iPhone, and then adding the .ipa file (the one I uploaded to Skillz) to my iPhone by using XCode Organizer. After doing that, the error was gone, and testing seemed to work out.

In subsequent builds, I got the same Sign Up error again because I had forgotten to upload and Sync my latest .ipa to the Skillz portal.

I also asked the Skillz team to help me test because I only have one device, and they have several they could test with at the same time. Besides that, it's also in their best interests that the game is solid Posted Image.

After all that, I had Skillz help me with the app description and the app rating. I then submitted the game to the App Store.

Post production

The first release of my app was with the Skillz 2.x SDK. I summarily made a new build with a 3.x version of the SDK. None of the Unity-side scripts appeared to change, though I made sure all of the non-Unity assets were updated.

I accidentally tested on a device that was not connected at the time. Once the game attempted to enter the Skillz portal, I got a notification that the device was not on the internet. Nothing happened after that for an indefinite period of time. This will be a cause of frustration for players, so in a subsequent update I will use Unity's functionality to determine whether the device is online when the player taps the play button. Keep in mind the device could still lose connection in the game (like if they're playing and get on an elevator, or they go out of wi-fi range). I informed my contact over at Skillz about it.


QUICK BUILDING REFERENCE (Dec 2013)

Here is the process I would undertake doing a build with Unity 3 from scratch in December 2013:

1. Follow the Skillz instructions for importing Skillz assets into your Unity game (but don't import any prefabs unless you're 100% sure they're Unity 3)
2. In Unity, make sure your build target is iPhone only and using the most recent iOS version settings possible. Make sure your orientation is Portrait.
3. In Unity, do a Build and Run. Select the Replace option (since I assume you want to build from scratch).
4. After Unity finishes what it's doing, open XCode to the created project if it's not there already.
5. Follow the Skillz instructions for integrating the Skillz SDK
6. Make sure your deployment target is iOS 7.0
7. Make sure your orientation is Portrait.
8. Make sure all your icons in the General tab of XCode are assigned.
9. Make sure all your necessary capabilities are assigned in the Capabilities tab of XCode.
10. Open Classes/AppController.mm, go to the function

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *window)

and comment out the landscape enumerations so that they are not included in the return value.

11. Under Build Settings, scroll to the section called "Apple LLVM 5.0 - Language - C++." There is an entry for "C++ Standard Library." Set it to "libstdc++"
12. Go to info.plist, add "View controller-based status bar appearance" and set it to NO.
13. Connect an iPhone to your machine and make sure XCode is set to build and deploy to it.
14. Go to the Product menu and select Clean
15. Click on the Play button to build and run.

Check out my homepage and social feeds

And my projects!

Report abuse Fast Diamond Shader For Unity Android

0 comments by Gamieon on Nov 14th, 2013

When developing Domino Arena, I experimented with using diamond/crystal shaders for the dominoes while deciding the look and feel of the game. I found a mobile diamond shader at  Wiki.unity3d.com by BurningThumb. It worked great for most PC's (there was one report of the dominoes not rendering however), but it was slow on my Asus EEE tablet. I could not get a frame rate better than 30 fps during normal game play.

The Unity profiler revealed that much of the time spent working in each frame was with transparent rendering; partly because of the dominoes, and partly because I called GUI.DrawTexture() way too much (which I fixed).

I'm very inexperienced with shader development, but I figured the least I could try was commenting out all code in the shader that had the word "Transparent" in it. To my surprise it actually had the desired effect: The frame rate went back up to 60 fps, and the diamond dominoes still looked like diamond dominoes with an unexpected caveat: They look transparent where they did not before. I don't exactly know why (again, I'm not an experienced shader developer) but it wasn't a big deal since dominoes don't obstruct each other during normal game play anyway.

Here's the shader code I ended up with (you can tell which parts I commented out):

code:
Shader "FX/Diamond Mobile"
{
  Properties {
    _Color ("Color", Color) = (1,1,1,1)
    _Fog("Fog", Color) = (0,0,0,0)
    _ReflectTex ("Reflection Texture", Cube) = "dummy.jpg" {
      TexGen CubeReflect
    }
    _RefractTex ("Refraction Texture", Cube) = "dummy.jpg" {
      TexGen CubeReflect
    }
    _RefractTexlow ("Refraction LowGPU", 2D) = "dummy.jpg" {
      TexGen SphereMap
    }
    _ReflectTexlow ("Reflect LowGPU", 2D) = "dummy.jpg" {
      TexGen SphereMap
    }

    _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _SpecColor ("Specular", Color) = (1,1,1,1)
        _Emission ("Emissive", Color) = (1,1,1,1)
  }

  SubShader {
    //Tags {
    //"Queue" = "Transparent"
    //}
    // First pass - here we render the backfaces of the diamonds. Since those diamonds are more-or-less
    // convex objects, this is effectively rendering the inside of them
    Pass {
      Color (0,0,0,0)
      Offset  -1, -1
      Cull Front
      ZWrite Off
      SetTexture [_RefractTex] {
        constantColor [_Color]
        combine texture * constant, primary
      }
      SetTexture [_ReflectTex] {
        combine previous, previous +- texture
      }
    }

    // Second pass - here we render the front faces of the diamonds.
    Pass {
      Fog { Color (0,0,0,0)}
      ZWrite on
      Blend One One
      SetTexture [_RefractTex] {
        constantColor [_Color]
        combine texture * constant
      }
      SetTexture [_ReflectTex] {
        combine texture + previous, previous +- texture
      }
    }
  }

  // Older cards. Here we remove the bright specular highlight
  SubShader {
    //Tags{"Queue" = "Transparent"}
    // First pass - here we render the backfaces of the diamonds. Since those diamonds are more-or-less
    // convex objects, this is effectively rendering the inside of them
    Pass {
      Color (0,0,0,0)
      Cull Front
      SetTexture [_RefractTex] {
        constantColor [_Color]
        combine texture * constant, primary
      }
    }

    // Second pass - here we render the front faces of the diamonds.
         
    Pass {
      Fog { Color (0,0,0,0)}
      ZWrite on
      Blend DstColor Zero  
      SetTexture [_RefractTex] {
        constantColor [_Color]
        combine texture * constant
      }
    }
  }

/////////// Start iphone code////////////////
//This will cause a nice gem texture to be rendered using the low-GPU textures defined in the inspector//
//This section of the code is provided by BURNING THUMB SOFTWARE, 2010//

  SubShader {
        Pass {
         
    Lighting On
            SeparateSpecular On
         
      Color (0,0,0,0)
    //  Offset  -1, -1
      Cull Front
      //Blend OneMinusSrcAlpha One
      SetTexture [_ReflectTexlow] {
        constantColor [_Color]
        combine texture * constant, primary
      }
    }

    // Second pass - here we render the front faces of the diamonds.
    Pass {
   

      Fog { Color [_Fog]}
      ZWrite on
      Blend One One
      SetTexture [_RefractTexlow] {
        constantColor [_Emission]
        combine texture * constant
      }
    }
             
  }
 
  // We need this for shadows
  FallBack "Diffuse" 
}


If you want to see it in action, just check out my game Domino Arena when it comes to Android!

Check out my homepage and social feeds

And my projects!

Report abuse A Unity PlayerPrefs wrapper

0 comments by Gamieon on Nov 13th, 2013

With every new project I try to make better tools to carry into my future projects. One of them has to do with the game configuration and PlayerPrefs. There are two issues I have with PlayerPrefs:

  • Using PlayerPrefs.Get... is slow in an Update() or an OnGUI() function (at least it was for me on mobile), and you have to grab the value in Awake() or Start() into a member variable and use that to avoid the issue.
  • No PlayerPrefs.GetBool() for yes/no toggling.

So I decided to make my own static class that not only addresses both issues, but does so in a way that I find convenient for organization. I call this class the "ConfigurationDirector."


The Preference Cache

For those of you who learn by staring at code first, or just want to copy it into your project, here you go:

csharp code:
public static class ConfigurationDirector
{
  #region Preference Cache
 
  static Dictionary<string,float> cachedFloatProps = new Dictionary<string, float="">();
  static Dictionary<string,string> cachedStringProps = new Dictionary<string, string="">();
  static Dictionary<string,int> cachedIntProps = new Dictionary<string, int="">();
 
  public static float GetFloat(string prefName, float defaultValue)
  {
    if (!cachedFloatProps.ContainsKey(prefName))
    {
      cachedFloatProps.Add(prefName, PlayerPrefs.GetFloat(prefName, defaultValue));
      PlayerPrefs.SetFloat(prefName, PlayerPrefs.GetFloat(prefName, defaultValue));
    }
    return cachedFloatProps[prefName];
  }
 
  public static void SetFloat(string prefName, float newValue)
  {
    PlayerPrefs.SetFloat(prefName, newValue);
    if (!cachedFloatProps.ContainsKey(prefName))
    {
      cachedFloatProps.Add(prefName, newValue);
    }
    else
    {
      cachedFloatProps[prefName] = newValue;
    }
   
    if ("Audio.MusicVolume" == prefName)
    {
      AudioDirector.MusicVolume = newValue;
    }
  }
 
  public static string GetString(string prefName, string defaultValue)
  {
    if (!cachedStringProps.ContainsKey(prefName))
    {
      cachedStringProps.Add(prefName, PlayerPrefs.GetString(prefName, defaultValue));
      PlayerPrefs.SetString(prefName, PlayerPrefs.GetString(prefName, defaultValue));
    }
    return cachedStringProps[prefName];
  }
 
  public static void SetString(string prefName, string newValue)
  {
    PlayerPrefs.SetString(prefName, newValue);
    if (!cachedStringProps.ContainsKey(prefName))
    {
      cachedStringProps.Add(prefName, newValue);
    }
    else
    {
      cachedStringProps[prefName] = newValue;
    }
  }
 
  public static int GetInt(string prefName, int defaultValue)
  {
    if (!cachedIntProps.ContainsKey(prefName))
    {
      cachedIntProps.Add(prefName, PlayerPrefs.GetInt(prefName, defaultValue));
      PlayerPrefs.SetInt(prefName, PlayerPrefs.GetInt(prefName, defaultValue));
    }
    return cachedIntProps[prefName];
  }
 
  public static void SetInt(string prefName, int newValue)
  {
    PlayerPrefs.SetInt(prefName, newValue);
    if (!cachedIntProps.ContainsKey(prefName))
    {
      cachedIntProps.Add(prefName, newValue);
    }
    else
    {
      cachedIntProps[prefName] = newValue;
    }
  }
 
  public static bool GetBool(string prefName, bool defaultValue)
  {
    return (GetInt(prefName, (defaultValue) ? 1 : 0) == 0) ? false : true;
  }
 
  public static void SetBool(string prefName, bool newValue)
  {
    SetInt(prefName, newValue ? 1 : 0);
  }
 
  #endregion
}


In short, what I do is call PlayerPrefs functions when I need values that are not cached in memory, and just read from memory at each subsequent Get. When I Set values however, I have to write to both cache and PlayerPrefs. Setting is, however, a fairly rare event.

Doing a dictionary lookup at each frame is of course not as fast as just grabbing the preference value in Awake() or Start() into a member variable and using that member variable in Update() or OnGUI(); but I don't notice the speed hit even on an iPhone 3GS and I like knowing that the preference is always up to date so long as I use the ConfigurationDirector properly.


Contexts


So you need to track your player's name, their high score, the class they're using for the current game, the color of their uniform, the game difficulty level, the music volume, the IP address of the most recent server they played on....and that's just the beginning!

I chose to bring order to that chaos by having my own system:

csharp code:
public static class ConfigurationDirector
{

  /// <summary>
  /// Player configuration settings
  /// </summary>
  public static class Player
  {
    /// <summary>
    /// Gets or sets the player name.
    /// </summary>
    /// <value>
    /// The name.
    /// </value>
    public static string Name
    {
      get {
        return GetString("Player.Name", "");
      }
      set {
        SetString("Player.Name", value);
      }
    }
   
    /// <summary>
    /// Gets the default hue.
    /// </summary>
    /// <value>
    /// The default hue.
    /// </value>
    public static float DefaultHue { get { return 62f; } }

    /// <summary>
    /// Gets or sets the player hue. This is a floating precision number between and including
    /// 0 and 360.
    /// </summary>
    /// <value>
    /// The player hue.
    /// </value>
    public static float Hue
    {
      get {
        return GetFloat("Player.Hue", DefaultHue);
      }
      set {
        SetFloat("Player.Hue", value);
      }
    }
   
    /// <summary>
    /// Sets the color of the player.
    /// </summary>
    /// <value>
    /// The color of the player.
    /// </value>
    public static Color PlayerColor
    {
      get
      {
        return ColorDirector.HSL2RGB(Hue / 360.0, 0.7, 0.5);
      }
    }
   
    /// <summary>
    /// Gets or sets a value indicating whether this player has seen tutorial.
    /// </summary>
    /// <value>
    /// <c>true</c> if this player has seen tutorial; otherwise, <c>false</c>.
    /// </value>
    public static bool HasSeenTutorial
    {
      get {
        return GetBool("Player.HasSeenTutorial", false);
      }
      set {
        SetBool("Player.HasSeenTutorial", value);
      }
    }
  }
 
  /// <summary>
  /// Audio configuration settings
  /// </summary>
  public static class Audio
  {
    /// <summary>
    /// Gets the default SFX volume.
    /// </summary>
    /// <value>
    /// The default SFX volume.
    /// </value>
    public static float DefaultSFXVolume { get { return 0.5f; } }

    /// <summary>
    /// Gets or sets the SFX volume.
    /// </summary>
    /// <value>
    /// The SFX volume.
    /// </value>
    public static float SFXVolume
    {
      get {
        return GetFloat("Audio.SFXVolume", DefaultSFXVolume);
      }
      set {
        SetFloat("Audio.SFXVolume", value);
      }
    }
   
    /// <summary>
    /// Gets the default music volume.
    /// </summary>
    /// <value>
    /// The default music volume.
    /// </value>
    public static float DefaultMusicVolume { get { return 0.4f; } }
   
    /// <summary>
    /// Gets or sets the music volume.
    /// </summary>
    /// <value>
    /// The music volume.
    /// </value>
    public static float MusicVolume
    {
      get {
        return GetFloat("Audio.MusicVolume", DefaultMusicVolume);
      }
      set {
        SetFloat("Audio.MusicVolume", value);
      }
    }
  }
 
  /// <summary>
  /// Network configuration settings
  /// </summary>
  public static class NetworkSettings
  {
    /// <summary>
    /// Gets or sets the game name.
    /// </summary>
    /// <value>
    /// The name.
    /// </value>
    public static string GameName
    {
      get
      {
        return GetString("Network.GameName", "My Game");
      }
      set
      {
        SetString("Network.GameName", value);
      }    
    }
   
    /// <summary>
    /// Gets the default port.
    /// </summary>
    /// <value>
    /// The default port.
    /// </value>
    public static int DefaultPort { get { return 12345; } }
 
    /// <summary>
    /// Gets or sets the port.
    /// </summary>
    /// <value>
    /// The port.
    /// </value>
    public static int Port
    {
      get
      {
        return GetInt("Network.Port", DefaultPort);
      }
      set
      {
        SetInt("Network.Port", value);
      }
    }
  }
 
  /// <summary>
  /// Current level settings.
  /// </summary>
  public static class CurrentSession
  {
    /// <summary>
    /// Gets or sets the difficulty.
    /// </summary>
    /// <value>
    /// The difficulty.
    /// </value>
    public static LevelDifficulty Difficulty
    {
      get
      {
        return (LevelDifficulty)GetInt("CurrentSession.Difficulty", (int)LevelDifficulty.Normal);
      }
      set
      {
        SetInt("CurrentSession.Difficulty", (int)value);
      }
    }
   
    /// <summary>
    /// Determines whether we are in table top mode
    /// </summary>
    /// <value>
    /// True if we are in table top mode; otherwise false
    /// </value>
    public static bool InTableTopMode
    {
      get {
        return GetBool("CurrentSession.InTableTopMode", false);
      }
      set {
        SetBool("CurrentSession.InTableTopMode", value);
      }    
    }
  }
 
  /// <summary>
  /// Unlocks.
  /// </summary>
  public static class Unlocks
  {
    /// <summary>
    /// Determines whether unlocks are enabled
    /// </summary>
    /// <value>
    /// True if unlocks are enabled
    /// </value>
    public static bool Enabled
    {
      get
      {
        return GetBool("Unlocks.Enabled", false);
      }
      set
      {
        SetBool("Unlocks.Enabled", value);
      }    
    }
  }
 
}


If I want to get the player's name, I do:

string name = ConfigurationDirector.Player.Name;

Doing this has two advantages: No more remembering the key you assigned to that preference from outside the ConfigurationDirector, and you know from the context (Player) that it's a player-specific preference. I also know that anything following "PlayerPrefs.CurrentSession" applies to the game in progress, and anything following "PlayerPrefs.Audio" must be related to volume controls. I'll let auto-complete do the walking for me.

Conclusion

This is how I manage configurations in my recent games, and it works well for my purposes. If you're not happy with how you maintain your game's configuration, or you forgot the preference key for the player name for the 8th time, it might be worth looking into doing something like this.

Check out my homepage and social feeds

And my projects!

Report abuse Unity: The referenced script on this behaviour is missing during LoadLevel

0 comments by Gamieon on Oct 17th, 2013

For the past few days I've been dealing with a puzzling issue in Unity: Every time I called Application.LoadLevel to change the scene in my game, this would appear in my console window:

The referenced script on this behaviour is missing!

This is despite the fact that I had no missing scripts! Based on my own logging, I determined this was happening before the next scene was loaded. I ultimately found that there was an internal issue with the prefabbed objects in the scene that was to be loaded (the ones that show in blue in the hierarchy window).

I was able to eliminate the warning by:

1. From the editor, open the scene that was to be loaded during the game.
2. Go through every prefabbed object and Revert to the original prefab state.
3. Go through every prefabbed object and change all the object properties back to the way I wanted them.

It was a bit of tedious work, but the warning stopped appearing after that. My guess is this happened because I deleted a script without detaching it from some of my prefab assets first.

I hope this helps someone out there who may be experiencing the same problem and just can't pin it down!


Check out my homepage and social feeds

And my projects!

Report abuse A way to do a numeric GUI.TextField in Unity in C#

0 comments by Gamieon on Sep 25th, 2013

Unity developers are familiar with

csharp code:
myText = GUI.TextField(myRect, myText);

But if you want a text field that only accepts numeric input, then you could accomplish it with some Regex filtering:

csharp code:
using System.Text.RegularExpressions;
...
myText = Regex.Replace(GUI.TextField(myRect, myText), "[^.0-9]", "");

Now suppose you wanted to contain it all in a function. The first thing that comes to mind is:

csharp code:
int NumberField(Rect r, int n)
{
   string result = Regex.Replace(GUI.TextField(r, n.ToString()), "[^.0-9]", "");
   return System.Convert.ToInt32(result);
}

Looks fine on the surface, but there's a glaring problem: It can't handle empty inputs. If you want to treat 0 as an empty input and change the function handle to it accordingly, you could do that. I chose to go this route:

csharp code:
int? NumberField(Rect r, int? n)
{
   string result = Regex.Replace(GUI.TextField(r, n.HasValue ? n.Value.ToString() : ""), "[^.0-9]", "");
   if (string.IsNullOrEmpty(result))
   {
      return null;
   }
   else
   {
      return System.Convert.ToInt32(result);
   }
}

Rather than processing an integer, I process a nullable integer. This way I can discern valid from invalid input without using sentinel values.

(Credit to Labs.kaliko.com for the expression ... and a special thanks to the author for actually including the namespace in their code snippet! )

Check out my homepage and social feeds

And my projects!

Report abuse Choosing an art style for my party game

0 comments by Gamieon on Sep 13th, 2013

I promised myself I would not do any more large projects without working in teams, but I never said anything about small ones. Even with the small ones however, I'm stuck with the same problem I have with all projects: I'm not that great at creative and artistic direction.

Consider my latest project "Domino Arena," possibly the smallest one I've done myself besides Paper Cowboys. It's a multiplayer "party" puzzle / action game where you have a playfield full of colored dominoes, and you manipulate places in the playfield where one domino knocks over more than one at a time such that as many dominoes as possible match your player's color.

You can see a concept video on YouTube:

I think it will take a tutorial and a little getting used to, but it could be fun. I'd at least like to pitch a beta around to see what people think when it's ready.

Now that the basic mechanics are defined, I need to figure out how the game will look. I've narrowed it down to three styles: Cartoon, "Jeweled" and semi-realism.

Cartoon

As a mobile developer, my first thought is always "cartoon" because all the popular and top selling apps that come to mind are all cartoony or at least have vibrant, pleasant art themes. Every "party" game I've played also shared similar traits. After looking at a bunch of mobile board game and Mario Party screen shots, I experimented with a scene using cell shading and six spotlights.

It's clear where all the dominoes are and everyone should be able to discern the blue from the gold dominoes...but the environment colors just don't look right to me. I'm concerned that if I make them brighter, then the dominoes will blend in more and players will have a more difficult time seeing them. If someone were to help with art direction, I bet this could work. Otherwise I can toy around with this a bit more.


Jeweled

During development I asked myself "what other games have game mechanics that rely on color?" The first game that came to mind was Bejewelled. After finding some gem shaders on the Unity Asset Store, I came up with a weird, wild theme of jeweled dominoes in dark scenes that keep the player's focus on the game's primary objects.

The word I would use is "bizarre." The mechanic and the style seem altogether foreign from anything I've played before...but that could be a good thing. I do like looking at the pretty colors, anyway. I could also have players "collect" the jeweled dominoes that match their color when a game is over, and have the grand total maintained on a leaderboard.


Semi-Realism

When I'm in doubt over style, I always turn to wood textures because i find them pleasant to look at. It's hard to see in the picture, but the dominoes are reflecting on the floor.

I thought this would look better as I was working on it; and the white dominoes on wood looked fine when the simulation began....but when they got colored, they just seemed out of place with the rest of the scene to me.


Final Thoughts

For me it's a close race between cartoony and jeweled with a lean toward jeweled. If I had to decide this moment, I would make a beta with a tutorial, three multi-player jeweled levels, computer player support, and just throw it out there and see what happens. If it gets a positive response, I'd work it to completion; otherwise it's still an eye catcher I can add to my portfolio.

 

Check out my homepage and social feeds

And my projects!

Report abuse Ideas For In-App Purchasing Do's and Don'ts

0 comments by Gamieon on Aug 26th, 2013

First off: If you haven't already, you should watch the video "Your first f2p [free to play] game: where you will go wrong." at Edery.org . This will tell you much more than this blog and from someone who has more experience. Thanks go to jbadams on GameDev.net for pointing this out.

One of my ad-supported mobile games has been on the market for the better part of a year, and I'm in the process of removing ads and putting in microtransactions to see if they will bring in more income. I'm a neophyte when it comes to designing apps around monetization; and while studying a few AAA apps doesn't make me an expert, it has given me some ideas that I'd like to try with my games and share with other developers to critique.

In Hamster Chase you can earn coins by skipping levels. In the next update, players will be able to buy them, too. Here is the in-app screen I designed to appear in the game when a player wants to skip a level but does not have enough coins:


These were the considerations I made in the design:

  • It appears immediately in the game when the player wants to use coins that they don't have.
  • Nowhere do you see the word "buy." I'm treating "buy" as an evil word, and also a redundant one since the price is already on the purchase button. Think about it: do you say to your friends "lets go get some dinner" or "lets go buy some dinner?" The only time I'll use "buy" is if the app has trouble fetching the price from the store portal.
  • I kept the words to a minimum, and relied more on icons and colors. From looking at it, I'm hoping a player can tell that they don't have enough coins, how many coins they need, and how many they will get for how much money.
  • The purchase button is larger than the cancel button.
  • The purchase button is a green color, and the background hue is close to being red. Reading Webpronews.com and Blog.kissmetrics.com I infer that red color tones communicate energy, excitement, and urgency. Green is associated with life, money, "green means go" and is easiest on the eyes to process. Yes the cancel button is a deep red, but I consider that a standard color for cancelling anything.

In-app screen design aside, here are some other ideas I'm running with in this next update:

DO: Have boosters that players can purchase to win the game more easily.

DON'T: Hide the fact that players can purchase boosters if they don't have any.

DO: Let players purchase a booster immediately when they want to use one and they have none.

DON'T: Make a player go to an entirely different place in the app to purchase something.

DO: Consider allowing players to also earn boosters without purchasing them.

DON'T: Give away so many free boosters that there's no point in purchasing them.

DO: Think carefully about every detail in the appearance of an in-app purchase prompt.

DON'T: Just throw together an in-app purchase screen with minimal effort.

DO: Consider having more expensive boosters to let players win the game more easily than cheaper boosters.

DON'T: Charge $37.99 for a booster.
(Counter-point: If someone is willing to pay $37.99 for it, why stop them?)

DO: Let the player discover they want or need something before presenting the opportunity to purchase it.

DON'T: Harass or pressure players into wanting something with repeated pop-ups or waiting screens.

DO: Consider selling players non-boosters that just make the game more fun, such as hats or skins.

DON'T: Try to sell anything to a player unless you either give them a free sample or explain what the item is for.

DO: Study the in-app flows of popular games similar to yours to learn how players find their products, and see how they are encouraged to buy them.

DON'T: Prioritize making money over making a genuinely fun game or having fun making one.
(Counter-point: It's easy for me to say because this isn't my full time job)

And now, my golden rule of in-apps:

DON'T: Force players to buy anything to finish a free to play game.

Report abuse Paper Cowboys Network Playable Unity Game Now Open Source!

0 comments by Gamieon on Aug 2nd, 2013

Paper Cowboys is now on GitHub in three flavors; each one utilizing a different network engine. Paper Cowboys is a simple side scroller that supports up to eight simultaneous players in co-op mode. You can get it by following this link:

Github.com


The three flavors are:

  • Unity native networking
  • Photon
  • uLink

Which one should you use? Well, I find that Photon works the best out of the box because of its room management system letting players find and join your game without you having to open firewall ports and such. However, you should not decide before reading this excellent blog:

Pepwuper.com

I don't believe I'm yet experienced enough to help you decide. Once I've actually had hundreds of players play all at once, then I'll know better.

Good luck!


Check out my homepage and social feeds

And my projects!

Report abuse My current projects and my next big goal

0 comments by Gamieon on Jul 20th, 2013

Over the past three years I've spent my free time releasing and maintaining three unique games for the mobile platforms (Hamster Chase, Hyperspace Pinball, Tiltz) and three games on the PC platform (Cycles3D, Hyperspace Pinball, Paper Cowboys) doing all the programming on my own. Along the way I've accumulated a fair bit of general game development knowledge that I can use in future projects; most recently, how to develop a network game in Unity.

Despite the past successes, I still feel unaccomplished. I'm therefore setting my sights on my next goal:

Help develop and release a game that is distributed over Steam.


Having a game on Steam, Desura and Indievania for professional game developers may be par for the course; but to me, having helped develop just one game that made its way to Steam would be my personal super bowl ring.

Could it be Dominoze? Maybe. As impressed as people have been with the latest concept art, there's not a solid design behind it. I don't think it will get there unless I find a talented designer and other help.

Could it be a successor to Paper Cowboys? It's possible. I was also tinkering with a tower defense game called "Lone Star Zombies" which imitates mechanics from the success Starcraft 2 mod "Mineralz" and a custom Killing Floor server I like to play on. Like with Dominoze, I seem to not have any inspiration for design. I can make a cookie cutter platformer or tower defense game, but there's a certain signature, personality, and quality of detail to a PC game that I just don't factor into my designs.

If there's one thing I've learned in the past 20 years, it's that I can program almost anything I put my mind to. I can be a helpful asset to a game development team who would have a part-time programmer like me. I may not quit my full time job developing medical software and put 40 hours into a week writing games, but my projects speak for what I can do in 48 hours, and what I can release in a year.

If you're on a team and need a programmer thoroughly familiar with Unity, or you're an individual who just feels like collaborating on a game, feel free to drop me a line.

In the meantime, I'll be working on the next major update for Hamster Chase: Boosters and hats!


Check out my homepage and news feeds

And my projects!

Report abuse "Paper Cowboys" personal Almost-Game-Jam: Hours 44-48

0 comments by Gamieon on Jun 8th, 2013

Hour 44

Got more sound effects set up, cleaned up the instructions a bit, and added a "Join random game" button. The Photon Network seems to be back up, so I had a chance to do some online testing with some folk at Develteam.com . Here are the bugs we found:

1. Ghost characters -- I don't know why, but sometimes a player duplicates themselves.
[FIXED] 2. Boss HP bar is misleading; if there are multiple players, then the boss has more HP...but the bar thinks there is always one player. Also, multiplying the HP by the player count is a bit excessive; maybe multiply it by the number of players times 80%.
3. It should be more obvious when a player is dead and waiting to respawn.
[FIXED] 4. On at least one occasion, players respawned even when everyone died
5. A number of errors in the Unity console that I won't spam you with here.

Hour 45

I -may- have fixed the issue where a player can appear more than once, and added a skull-and-crossbones icon that appears to the left of a player's name when they're dead. I also made a decision knowing it's probably a bad one: I'm going ahead with level 3. I managed to get the background art done, and the camera to follow the player when jumping vertically, and have the player die if they fall off the bottom of the screen.

I'm rather fond of the background art -- I drew it by studying a picture of the grand canyon and just "sketching it."

Hour 46

I finished level 3 sooner than expected; but that's probably because I cut corners to wedge in more time for overall testing. I recycled the same old enemy prefabs and put almost no effort into the boss. It was a pleasantry to see that I could still make it look half-decent with just one "stepping stone" bitmap instead of the several I had planned on drawing. I think this level is the hardest because it has a strong respawning enemy presence. I still haven't been able to beat it solo.

The rest of the time was spent on adding links to the title screen and game-wide testing.

Hour 47

This hour was devoted to bug fixes:

  • Extreme slowness after a short while playing
  • Players were invincible in level 1
  • Mouse cursor invisible in the game menu
  • Game won't end if everyone is dead sometimes
  • Took out $ from score -- everyone kept asking if they could buy stuff with it
  • Increase shotgun range

I also starting working on a bug where you sometimes could not start or join a game.

Here's how my desktop looked for a good portion of this hour:

Hour 48

I spent a lot of this hour fixing the "Sometimes you can start / join a game." bug. I tried to get gamepad integration in as well, but I ran out of time. I might have to turn this into an extended "50 hour" jam.

THE FINAL PRODUCT

Bugs I didn't fix because it was too late
 

  • The PC Version has no way to quit without closing the window
  • No gamepad support
  • Sometimes you can jump extra high
  • Sometimes you can't jump toward a ledge but you can't get through it
  • Level 2 Boss Fight: You can respawn in front of the train and not see the boss
  • Level 3: When you respawn, the camera doesn't follow you down, so you're pretty much toast if you die.
  • Level 3: Sometimes you can't move (got it to happen once) 
     

I could have just settled on two levels with less bugs; but I let the chaos side of me, the "cowboy coder" if you will, make the call. I'm paying the price for it, but you know what, this was all done in good fun. It was a very nice holiday from the usual grind of serious game development.


The end of this blog line?

Nope...I still need to write the post-mortem! Stay tuned!


Check out my homepage and news feeds

And my projects!