Tag Archives: iPhone

OpenFeint 2.7.5 and Achievement Notifications

I’ve been adding OpenFeint 2.7.5 to my iOS game Pawns!, and ran into what I suspect is a bug. When an achievement is earned, the user is not getting notified. (I found developers on a Torque forum who ran into something similar with 2.7.5.)

This seems to have been introduced when OpenFeint added their new API for setting achievements to be partially complete. Or maybe it has something to do with their new GameCenter integration.

Poking around the OpenFeint code and its Unity wrapper, I found that when the Unity script calls

OpenFeint.UnlockAchievement(MY_ACHIEVEMENT_ID);

the following Objective-C code eventually executes in AppController+OpenFeint.mm:

// Unlock the achievement.
[OFAchievementService updateAchievement:[args objectAtIndex:1]
					 andPercentComplete:100
					andShowNotification:FALSE
					  onSuccess:success
					  onFailure:failure];

Why is notification explicitly turned off here? Was it deliberate? I have no idea. A quick fix might be to set FALSE to TRUE. But, you risk losing that change the next time you upgrade OpenFeint’s code.

I noticed just below this code that the OpenFeint plugin is prepared to handle another command from Unity, “UpdateNotification”, that takes additional arguments, namely the percent complete and whether to show notifications:

	// UpdateAchievement //
	else if(OF_CMD(@"UpdateAchievement"))
	{
		// Set up the delegates.
		OFDelegate success(self, @selector(onAchievementSuccess));
		OFDelegate failure(self, @selector(onAchievementFailure));
		
		// Unlock the achievement.
		[OFAchievementService updateAchievement:[args objectAtIndex:1]
							 andPercentComplete:[[args objectAtIndex:2] doubleValue]
							andShowNotification:[[args objectAtIndex:3] boolValue]
									  onSuccess:success
									  onFailure:failure];
	}

Looks useful! The only problem is that they haven’t yet added this command to the Unity C# wrapper.

But that’s easy to fix! Just add the following to OpenFeint.cs in your Unity project:

	// UpdateAchievement //
	//
	// Unlock an achievement.
	//  - achievementId:      The ID of the achievement.
	//  - percentComplete:  How much to unlock
	//  - showNotification:   Whether to notify
	//
	//	events				OnAchievementUnlocked
	//
	static public void UpdateAchievement(long achievementId, int pct, bool showNotif)
	{
		PerformCommand(String.Format("UpdateAchievement|{0}|{1}|{2}", achievementId, pct, showNotif));
	}

Now to unlock an achievement I call:

OpenFeint.UpdateAchievement(MY_ACHIEVEMENT_ID, 100, true);

This seems to fix the notification issue, and gives Unity scripts a way to set the percentage-complete of an achievement (I didn’t test this.) I also prefer this solution because it is very likely that OpenFeint will themselves add this to their Unity wrapper class in the future.

(If you are really paranoid, you could put this code somewhere else so that future OpenFeint wrapper changes won’t overwrite it. All it does is format a particular PlayerPref string that triggers the OpenFeint plugin.)

The Case of the Lingering Collider

Unity 3 for iPhone has some new behavior that I just ran into. When switching from one Pawns puzzle to the next, my code destroys one set of objects then creates others. This has worked for years, but in Unity 3 builds running on an iPhone, I noticed that the colliders of just-destroyed objects are now sometimes hitting objects being created afterwards.

This only happened when running on the actual device, not in the editor. Weirdly, I only see it happening for colliders on a particular type of object (the red checkers.)

My workaround was to deactivate each object just before destroying it:

	foreach (GameObject gameobj in transients)
	{
            gameobj.active = false;  // <-- NEW
	    Destroy(gameobj);
	}
        // .. create new objects, etc..

I should probably file a bug on this, but since it doesn't happen for all my objects I can't say for certain that I have the problem entirely figured out. So I'll need to find time to work up a solid example. What little time I have at the moment is spent on a couple thorny GUI issues (will post about that soon.)

Sorry this is so vague, but I figured that it was worth mentioning on the off-chance that it helps someone. If I learn more I'll post.

UnityGUI Unresponsive on iPhone Retina Displays (Updated 10/28/2010)

A tester reported that Pawns for iPhone was not working on his 4th generation iPod Touch (with Retina display.) Specifically, many of the menu buttons were very flaky, sometimes requiring multiple taps before they’d register.

After some investigation I isolated the cause [EDIT: or maybe not? See my updates at the end of the post.] It appears that UnityGUI buttons are extremely sensitive to movement of the finger, when run on retina displays. The slightest movement of the fingertip on a retina display causes the tap to be ignored. (Version info: Unity 3.0 for iPhone; non-HD build of the game.)

I believe the problem is with Unity’s translation of touches into “clicks”. There is a movement threshold value (probably 5 to 10 pixels) beyond which a touch is no longer treated as a single tap on a Button. I believe Unity is using the same threshold value on retina displays, and that threshold is too low for the higher-resolution.

If I’m right, anyone shipping an iPhone game that relies on normal UnityGUI click logic is taking a serious risk at the moment. If you are getting complaints about unresponsive controls on retina displays, this is quite possibly the culprit.

I have filed a bug of course, and in due time I expect Unity Tech will change the threshold, or possibly something else I haven’t thought of, and all will be well.

In the meantime, I’ve got a game to ship! So, what to do?

My plan was to add my own touch-processing logic, using the same techniques I recently used to make the ScrollView control respond to finger drags.
However, I found to my dismay that most of my remaining UnityGUI menus happen to be using GUILayout, not GUI. This means that I don’t actually know where the buttons are being displayed on the screen. And without that Rect, I can’t do touch detection.

So I am faced with the choice of waiting for a possible fix, or of converting my GUILayout menus to GUI. Doing the layout myself is not rocket science, but it is tedious to rewrite the menus and retest every iPhone and iPad resolution and orientation I plan to support.

UPDATE: See the comments below. It turns out there IS a way to get the rectangle of a GUILayout control. I will post some sample code once I’ve implemented a workaround for the responsiveness issue.

UPDATE October 28, 2010: I have coded the workaround. But: I am no longer able to reproduce the original problem! Either something has changed about my test app, or I’m missing an important detail.

I wasn’t seeing widespread reports of this problem so the fact that it doesn’t always occur makes sense. In a way, a relief. But I would dearly like to know how it happened originally, and not just because it would have saved me some effort rewriting the tap logic. The effect was very specific to button presses on a retina display, and all my testers noticed it. Unfortunately without owning a retina display myself I am not going to get to the bottom of this any time soon.

Coming soon- Pawns for iPad and iPhone!

The page is up for my forthcoming game, Pawns for iPad and iPhone! More than just a port of the Mac & Windows game, this version has many more puzzles, rated for difficulty. The user interface has been redesigned for touch screens. Not to mention the two most-requested features of all: knights and queens!

The game is currently in beta-testing and I hope to release it in about a month. Stay tuned!