Simple Action Hooks

If you need to add a simple hook that can be subscribed to and then called when something specific happens, you can do it with System.Action.

For example, I needed a few objects to be notified when the player would enable or disable certain features using a toggle checkbox.  In the class managing the UI I added the following line:

    public static System.Action OnEnabledChanged;

When the toggle was changed by the player, the following code is executed:

            if (OnEnabledChanged!=null)
                OnEnabledChanged();

In each of the other objects that needed to be notified of this event, I then added the following line:

        UIManager.OnEnabledChanged += onEnabledChanged;

where onEnabledChanged is a local function that is called when the UIManager responds to the player tapping on the checkbox.  The event can be subscribed to by multiple objects, though the only caveat is to make sure if a subscribed object is destroyed it unsubscribes from the event by using:

        UIManager.OnEnabledChanged -= onEnabledChanged;

Or you’ll start getting errors.

If you need to pass a parameter to your subscribed events, then you can do so with a simple modification:

    public static System.Action<bool> OnEnabledChanged;

and

            if (OnEnabledChanged!=null)
                OnEnabledChanged(isEnabled);

Your subscribed functions will now need to accepted a bool parameter (for example).

OnDisable & OnApplicationQuit

In my latest project, I ran into an issue with OnDisable being fired when I stop the project running in the editor.  I’d get a host of errors about destroying transforms and not gameobjects.  Now I didn’t do any of that, but I did have an OnDisable routine that moved all the children of the disabled gameobject into a pool for reuse at a later point.

Turns out that all GameObject’s are disabled when you exit run mode in the editor, and they all have OnDisabled called one last time.  Not sure why this caused the error I was seeing and not even sure it was a real problem, but it was ugly seeing all those red exception errors fill my console window.

OnApplicationQuit to the rescue! After some googling I found that others have been having the same problem and it is a pretty simple solution.  Just add a private bool to your script and the Monobehavior method ‘void OnApplicationQuit()’ which just sets this bool to true.  Now in your OnDisabled method you can check to see if that bool is true & do nothing if it is!

OnApplicationQuit is called before the OnDisabled methods, so that flag gets set and your other methods just return. Simple & Clean!

private bool applicationIsQuitting;
void OnApplicationQuit()
{
	applicationIsQuitting = true;
}
void OnDisabled()
{
	if (applicationIsQuitting)
		return;
	Debug.Log("OnDisabled");
}

Dangers of copying files (Google Play Services Lib)

Had an issue today where after upgrading to the latest version of the Google Play Services the build process threw up a ton of  cryptic error messages like “Temp/StagingArea/android-libraries/google-play-services_lib/res/values/common_colors.xml:4: error: Resource entry common_signin_btn_dark_text_default is already defined.”

Turns out that while upgrading the Google Play Services folder, instead of replacing the old folder completely, the new folder was merged with the old one.  This left the old ‘colors.xml’ file which then conflicted with the new ‘common_colors.xml’ file.  Deleting the old folder and then copying in the new folder fixed it!

Obviously we figured it out, but it did manage to waste 30 minutes.  Hopefully, by writing this entry, I’ll remember the next time this happens, and maybe even help some other unfortunate soul from wasting their own 30 minutes.

 

c# Jagged Arrays

While working on a new game app, I needed to initialized a multi-dimensional array upon declaration.  I initially used a two dimensional array declared as such:

readonly TrackType[,] validTypes = {{TrackType.none},
{TrackType.one, TrackType.two, TrackType.three}};

This worked fine and the array was declared and initialized correctly.  I then decided I wanted to extract a row from this array and work on it, rather than always using two indexes as I processed the entries.  However, with a multi-dimensional array it’s not possible to do this implicitly.  The solution was to create a Jagged Array.  Each element is accessed in a similar way, but it allows you to grab a pointer to a row of the array, which is what I wanted.

The syntax for defining and initializing it during declaration is quite different however, and this is what I ended up with:

readonly TrackType[][] validTypes = new TrackType[][] {
new TrackType[] {TrackType.none},
new TrackType[] {TrackType.one, TrackType.two, TrackType.three}};

More typing, but it gets the job done.

Re-sizing iOS screenshots

While not a perfect solution, grabbing screens at iPhone 6 Plus resolution and then down-scaling for iPhone 6 & iPhone 5 screen sizes is a lot quicker.

To do this I use the mogrify command from the amazingly useful ImageMagick toolset.  However, as the aspect ratio for the iPhone 5 is slightly different to the iPhone 6 Plus, you need to add a ! to the end of the resize options as follows:

mogrify -resize 1136×640! *.png

This will resize the images exactly to the iPhone 5 landscape size, ignoring any aspect ratio, otherwise you get 1136×639, which just won’t do.

For iPhone 6 landscape size I use:

mogrify -resize 1334×750! *.png

Note that mogrify will overwrite the source file, so I make a directory for each size I want and copy the iPhone 6Plus sized files in.

Just as a FYI, the iPhone 6Plus sized images are 2208×1242 (landscaped)