Author Archives: Matt

OpenFeint and Unity 3.3, iOS SDK 4.2

Developers seem to be having quite a few problems trying to integrate the latest versions of OpenFeint (2.8, 2.9) with their Unity 3 iOS games. See the following for some discussions of the problems:

Unity Forum: OpenFeint-iOS-2.9-problems
Unity Forum: my-iPhone-application-is-getting-crash
Answers.Unity3d: crash-at-first-launch-with-openfeint.html

To save time as I try to put out a bug-fix for Pawns, I decided to stick with OpenFeint 2.7.5.

However, I ran into some of the problems people had with later versions of OpenFeint. Specifically, the app was crashing with one of the following errors when I closed the OpenFeint dashboard to return to the game:
mi_cmd_stack_list_frames: Not enough frames in stack.
or:
[CAMediaTimingFunctionBuiltin deactivate]: unrecognized selector sent to instance

So apparently the upgrade to Unity 3.3 and/or iOS SDK 4.2 is where this problem started, not because of changes to OpenFeint. The solution, as reported by developers using later versions of OpenFeint, was to comment out calls to UnitySetAudioSessionActive in the dashboardWillAppear, dashboardDidDisappear methods in AppController+OpenFeint.mm:

// OpenFeintDelegate //
- (void)dashboardWillAppear
{
	unityPaused = YES;
	//UnitySetAudioSessionActive(false);
	UnityPause(true);
}

- (void)dashboardDidDisappear
{
	unityPaused = NO;
	//UnitySetAudioSessionActive(true); 
	UnityPause(false);
}

Another symptom I noticed was that when my game was exited under iOS 4 and then brought back to the foreground, the game would appear but then immediately quit (though iOS still listed it as running for some reason.) Bringing it forward a second time would basically run it over from scratch. I concluded that it was crashing on resume, and the culprit was the same call to UnitySetAudioSessionActive, this time in two other delegates. Commenting those out fixed the issue:

- (void) applicationDidBecomeActive:(UIApplication*)application
{
	printf_console("-> applicationDidBecomeActive()\n");
	
    if (gDidResignActive == true)
    {
	    //UnitySetAudioSessionActive(true);
	    UnityPause(false);
    }
	
    gDidResignActive = false;
	
	[OpenFeint applicationDidBecomeActive];
}

- (void) applicationWillResignActive:(UIApplication*)application
{
	[OpenFeint applicationWillResignActive];
	
	printf_console("-> applicationDidResignActive()\n");
	// UnitySetAudioSessionActive(false);
	UnityPause(true);
    gDidResignActive = true;
}

The fact that this problem apparently persists in OpenFeint 2.8 and 2.9 isn’t good. I get the distinct impression that OpenFeint’s Unity wrapper is not very well supported.

Pawns! and the iPad 2

I’ve just learned that Pawns! is not working properly on the iPad 2. The arrows that you place on the board cannot be seen properly, but instead are entirely black.

It continues to work on most, if not all, other iOS devices. I’ve tested many of them personally. Nonetheless, I’ve removed Pawns! and Pawns! Lite from the iTunes app store for the time being.

Pawns! 1.1 Released: OpenFeint, Game Center Achievements

Pawns! 1.1 is now available in the App Store. This update adds 14 earnable achievements, including Knight’s Tour, 100 Pawns, and the greatest achievement of all, Grandmaster.

Pawns! 1.1 also integrates with OpenFeint and Game Center. Logging into these services automates the time-consuming process of bragging about your Pawns achievements to your friends. Now, all you have to do is solve puzzles– the bragging is done for you automatically!

To celebrate the new version, Pawns! is on sale this week for only $0.99 USD (or non-U.S. equivalent.) Sale ends Dec 27th.

Links:
Pawns! home page
Buy it here

Fixing Unity and OpenFeint iPad Rotation Issues

Unlike iPhone games, Apple requires iPad games to support orientations symmetrically. For example, if a game works in one landscape orientation, it should also work when rotated 180 degrees. And this should be true whether the iPad is rotated before the game is run, or while it is played.

There are well-known Unity scripts to address the two major rotation issues most iPad developers run into. I’ll review those solutions first, then describe how to fix new problems introduced with OpenFeint.

Basic iPad Rotation Behavior

There are two behaviors that Unity games should implement for the iPad:
• Change the game’s orientation when a new (supported) orientation occurs
• Turn off the “rotating black square” seen as iOS rotates its menu bar (the one that is normally hidden behind your Unity game.)

I take no credit for the following solution, although I combined them into one script for my own convenience:

public class iPadRotationFixer : MonoBehaviour 
{
    void Start()
    {
        // Turn off the visible iOS menu rotation
        iPhoneKeyboard.autorotateToPortrait = false;
        iPhoneKeyboard.autorotateToPortraitUpsideDown = false;
        iPhoneKeyboard.autorotateToLandscapeLeft = false;
        iPhoneKeyboard.autorotateToLandscapeRight = false;
    }
	
    void FixedUpdate () 
    {
        // In this example, only the two landscape modes are supported
        if ((Input.deviceOrientation == DeviceOrientation.LandscapeLeft) 
                && (iPhoneSettings.screenOrientation != iPhoneScreenOrientation.LandscapeLeft))
        { 	
            iPhoneSettings.screenOrientation = iPhoneScreenOrientation.LandscapeLeft;
        }
	   
        if ((Input.deviceOrientation == DeviceOrientation.LandscapeRight) 
                && (iPhoneSettings.screenOrientation != iPhoneScreenOrientation.LandscapeRight))
        { 
            iPhoneSettings.screenOrientation = iPhoneScreenOrientation.LandscapeRight;
        }
    }
}

Just put this script on an empty GameObject in every scene of your game. (I usually name the object something like “ziOSRotationFixer” so that it sorts to the bottom of the Hierarchy view.) The Start method is only needed in the initial scene, but does no harm to run it more often.

Startup Logo

In your iOS project settings you can also set the Default Orientation, but I don’t think it matters for iPad games. Unity for iPhone 1.7 and earlier had a problem where the Unity splash screen would only show in one orientation on the iPad- you can still find old discussions about how to fix that, but as of Unity 3.0 the splash screen orients correctly on startup.

OpenFeint and iOS 4.2

The above solution has worked with only minor changes since the iPad first came out. So you can imagine my dismay when a tester found rotation problems after I added OpenFeint to Pawns. The tester found that when he double-clicked the Home button during a game, the multitasking bar would sometimes be upside-down. I found the game’s OpenFeint dashboard had the same problem.

Both problems stemmed from my misuse of OpenFeint. Just as Unity needs to be told to rotate the screen orientation, OpenFeint also needs to be told. This just requires adding a couple lines to the FixedUpdate method above, which I’ve marked as new.

    void FixedUpdate () 
    {
        if ((Input.deviceOrientation == DeviceOrientation.LandscapeLeft) 
            && (iPhoneSettings.screenOrientation != iPhoneScreenOrientation.LandscapeLeft))
        { 	
            iPhoneSettings.screenOrientation = iPhoneScreenOrientation.LandscapeLeft;
            OpenFeint.SetDashboardOrientation(DeviceOrientation.LandscapeLeft); // ** NEW **
        }
	   
        if ((Input.deviceOrientation == DeviceOrientation.LandscapeRight) 
            && (iPhoneSettings.screenOrientation != iPhoneScreenOrientation.LandscapeRight))
        { 
            iPhoneSettings.screenOrientation = iPhoneScreenOrientation.LandscapeRight;
            OpenFeint.SetDashboardOrientation(DeviceOrientation.LandscapeRight);   // ** NEW **
        }

        // The above is for Landscape. Don't forget to add Portrait cases if you need them
    }

(Source: http://forum.unity3d.com/threads/50822-OpenFeint-iPad-screen-orientation-on-startup)

This solution works great when the orientation changes as the game is running.

However, the initial OpenFeint dialog can still show upside-down! This problem was discussed in the above thread and in other places, but there doesn’t seem to be widespread understanding of the cause or how to fix it. So I looked into it myself and came up with the following.

The problem is simply that, when you first set up the OpenFeint plugin for Unity, you have to specify the startup orientation. OpenFeint relies on this for the initial orientation.

(Why is the initial orientation fixed and not dynamic? I think it’s mainly because it was originally developed for the iPhone. Also note that the developer can trash OpenFeint’s Portrait or Landscape resources if the game doesn’t need them to save space. So OpenFeint can’t just orient itself dynamically to any direction it pleases. It needs to be told what orientations to use.)

Happily, we can make it check the device’s orientation by adding a few lines to the OpenFeint initialization code in the Xcode project. This is going to work like the FixedUpdate method: we’ll explicitly code for the orientations we need to support.

Here is the old code that we’ll change. It takes the Initial Dashboard Orientation setting and puts it right into the dictionary. (Note: this is the same chunk of code that gets edited when you want to enable Game Center.) Currently the code is in the file classes/AppController+OpenFeint.mm.

    NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:
         [NSNumber numberWithInt:UOF_INITIAL_DASHBOARD_ORIENTATION], OpenFeintSettingDashboardOrientation,

The replacement code checks the device’s orientation dynamically. Again, I am only supporting left and right landscape modes for my game:

    id orientation = [NSNumber numberWithInt:UIDeviceOrientationLandscapeLeft];
    if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight)
    {
        orientation = [NSNumber numberWithInt:UIDeviceOrientationLandscapeRight];
    }
    NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:
                orientation, OpenFeintSettingDashboardOrientation,

Now OpenFeint’s initial orientation is correct, and so is the iOS multitasking bar.

Note that this code may get overwritten if I install a new version of OpenFeint’s API into my project. That’s the downside of going in and tweaking OpenFeint’s Unity plugin or their code. Like my last tweak (adding support for percent-complete achievements) it’s possible OpenFeint will fix it themselves in a future version. While they are at it, maybe they’ll add the Game Center switch to the Unity plugin as well. Then there would be no need to edit this code at all.