WARP gce is now available

WARP gce - Only (good) Space Trader in Game Center


Download from iTunes - it's FREE!

Tuesday, February 4, 2014

Unity3d and "strings"

I've been using the Unity Asset Store a lot and have downloaded quite a lot of free assets and purchased my fair share as well.

One thing I see a lot in many of the C# scripts (probably in Javasc, oops  UnityScript too) is the repeated use of using plain old STRINGS in critical, e.g. game breaking methods and processes.

I mean we use strings all of the place and it seems like Unity / C# is no exception especially since you define and use both TAGS and LAYERS and they are of course strings!

If I have to type the contents of a string (like "com.meachware.levelOneLeaderboard") more than ONCE; I must create a constant for it. <- period!

The kicker is the simple fix in C# is this:

using UnityEngine;
using System.Collections;

namespace com.ootii.Messages {
    public class Type {

        // A list of Message types.
        public const string all = "EVERYONE";
        public const string filter = "FILTER";
        public const string target = "TARGET";

Note: This example is taken directly from the awesome Unity Dispatcher asset I just purchased and even he didn't use constants (that's the reason for the "namespace").

Yup, create a new class and list out all your string constants. Then in ANY other class when you need to access them, instead of typing "FILTER" you simply use "Type.filter" (without the quotes).

Oh AND you get, for FREE type-ahead / autocorrect! How sweet is that!

Now I have not done any benchmarks to see if you have say 1200 const string entries it impacts memory / performance but I gotta believe the benefits outweigh any impact.

PS Full credit for this concept (at least where I learned it from) is the Unity Learn series / Stealth project. Here's the link where they talk about Tag Management.

Wednesday, December 4, 2013

From Dev to Release version

...without deleting the app from your device.

Back story:
I do a bunch of testing on all my devices AND I also use (play) live apps on my device(s). In the past I resorted to deleting my test build app and then installing my newly released version, thus loosing all my IAP's and other non-Game Center stats(2).

I've recently started using this method:
Once my new version has been released and is available on the store I take a copy of my current project and reset the version back to the previous one and build for the device. Now I install this version onto my devices. Then either with iTunes (after updating the app) or the App Store on each device, I download and install the updated (released) version. This allows me to install the new updated version without loosing any of my saved data.

1: It's worth mentioning that if you install your live (released) version on your device and then you install your new test build with Xcode, your app will not show up in the list of Applications as (I'm spit-balling here) it replaces the production version of your app. The downside is you cannot get at the app bundle via Xcode.
2: All my game have a resync Game Center functionality (I guess just for me).

Monday, October 14, 2013

GKSession didChangeState delegate not working in iOS 7

So the GKSession transfer code that has been working ever since iOS 4.0 decided to STOP working (1/2 way) under iOS 7. Yeah, right? what else is new? :-p

The specific error or problem was that the connect code to display the alert where the user drags a slider for the desired number of vouchers to transfer, was not showing on iOS 7 device.

The iOS 7 devices DID receive vouchers so that meant the GKSession WAS valid.

So, in debugging it I found that even though the delegate was set, the didConnectPeer callback was firing but the didChangeState: WAS NOT.

So.... an easy-peasy kludge of a patch now allows iOS 7 devices to transfer vouchers to their iOS 6 (and iOS 5) brethren.

- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)thePeerID toSession:(GKSession *)theSession 
self.session = theSession;
self.session.delegate = self
    self.peerID = thePeerID; 
    [self.session setDataReceiveHandler:self withContext:NULL];
    [picker dismiss];
    picker.delegate = nil;
    float sysVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (sysVersion > 6.9) {
       if (!didConnect)
           [self session:self.session peer:self.peerID didChangeState:GKPeerStateConnected];

 Full disclosure: I also added a boolean flag so that the GKPeerStateConnected "state" will only fire once, regardless of "where" it came from.

        case GKPeerStateConnected:
            if (!didConnect) {
                didConnect = TRUE;
                NSLog(@"Peer %@ Connected", self.peerID);
                [self performSelector:@selector(promptForQty) withObject:self afterDelay:1.0];
                self.statusLabel.text = @"Connected";
                [self.launchShareButton setTitle:@"Stop" forState:UIControlStateNormal];
                [self.launchShareButton setTitle:@"Stop" forState:UIControlStateHighlighted];
                [self.connectingActivityIndicatorView stopAnimating];