iOS

Using the OpenFeint Unity iPhone Plugin

apple ios phone and womanNow that you have the OpenFeint iOS plugin installed, youll want to start using the methods, events, and properties found in Plugins/OpenFeint/OpenFeint.cs inside your Unity project folder. The following is a discussion on some common tasks you might perform while integrating OpenFeint into your project.

The OpenFeint class.

The OpenFeint class is declared inside OpenFeint.cs. It is a static class (meaning all methods, properties, variables, etc. are declared as static). Unlike most scripts in Unity, you should not try to attach this to a GameObject as a component. The OpenFeint class is designed to be used like a series of utility functions and properties (much like Mathf or Random in Unity).

The OpenFeint class bridges the gap between your Unity scripts and the OpenFeint Objective-C code which lives in your Xcode project. When you call a method or property from the OpenFeint class, a message immediately gets sent to Objective-C code which then gets passed on to OpenFeint iOS. Information also gets passed to the OpenFeint class from Objective-C, and you can retrieve this information whenever it is necessary. The OpenFeint class divides communication with OpenFeint into four different types:

  • Methods These are basically just functions that directly call an analogous OpenFeint function.
  • Properties These are technically functions but are used like variables in your scripts. They allow you to get some state information about OpenFeint.
  • Events Think of these as messages that get sent out from OpenFeint when something occurs. You can subscribe to these events to be notified when things occur.
  • Delegates Delegates are essentially functions that you supply which can then later be called to give you a result of a non-instantaneous query.

Examples of how to use each of these types are provided in the next section.

Using the OpenFeint class

The following is a discussion on how to use the OpenFeint class within your Unity project. While the OpenFeint iOS class itself has been written in C#, all of the methods, properties, events, and delegates it provides can be used in Javascript Unity scripts. When there are differences, we will show you both the C# and the Javascript usage.

One of the simplest and quickest ways to get started is to simply launch the OpenFeint dashboard. In one of your scripts, simply do the following:

OpenFeint.LaunchDashboard();

Notice how the OpenFeint class name precedes the method name. Whenever you need to access something from the OpenFeint class (including delegate and enumerated types), you should precede it with the OpenFeint class name. Now if you wanted to launch the dashboard to a specific page, you would do something like this:

OpenFeint.LaunchDashboard(OpenFeint.eDashboardPage.Leaderboards);

Youll notice were using the eDashboardPage enumeration here, which can be found at the top of OpenFeint.cs. Now say you want to submit a high score. You can do that very easily by using one of the SubmitHighScore methods.

OpenFeint.SubmitHighScore(47, 99999);

Youll notice that we used the

SubmitHighScore(long score, long leaderboardId)

method. The reason that there are four different versions of SubmitHighScore is to provide flexibility for you. For instance, you could create an enumeration of all of the leaderboards in your game, and pass an enumerated value to the leaderboardId parameter. The properties provided in the OpenFeint class allow you to get (and sometimes set) certain state information about OpenFeint. For example, you can easily get whether or not the user has approved the use of OpenFeint iOS on their device.

if(OpenFeint.hasUserApprovedFeint) {
	// Code goes here.
}

You can also set some properties, such as whether or not you want to allow notifications at this time.

if(OpenFeint.allowNotifications) {
	OpenFeint.allowNotifications = false;
 }

Events are a convenient way for you to be notified when something occurs in OpenFeint iOS. In fact, events are necessary if you want to implement challenges or the network save card features of OpenFeint. Lets say you wanted to be notified when a user logs in and then perform some operation. You would subscribe to the OnUserLoggedIn event with a function of your own. This function must conform to the UserLogInEventHandler delegate. Heres an example: C# Example:

// Method signature must match that of the UserLogInEventHandler delegate.
private void MyUserLogInHandler(string userId) {
	Debug.Log("User " + userId + " logged in.");
}
...
// When you want to subscribe to the event (perhaps in Awake or Start):
OpenFeint.OnUserLoggedIn += new OpenFeint.UserLogInEventHandler(MyUserLogInHandler);

Javascript Example:

// Function signature must match that of the UserLogInEventHandler delegate.
function MyUserLogInHandler(userId : string) {
	Debug.Log("User " + userId + " logged in.");
}
...
// When you want to subscribe to the event (perhaps in Awake or Start).
OpenFeint.OnUserLoggedIn += OpenFeint.UserLogInEventHandler(MyUserLogInHandler);

Now, whenever a user logs in, the MyUserLogInHandler function that you supplied will be called. You can unsubscribe from this event by doing the following:

OpenFeint.OnUserLoggedIn -= MyUserLogInHandler;

NOTE: You must handle unsubscribing on your own. Since the OpenFeint class events are static, subscriptions persist across level loads. So if you subscribe to an event inside a script attached to a GameObject that gets destroyed upon level load, you must unsubscribe to that event when the object is destroyed (perhaps in OnDisable). If you dont unsubscribe from an event and the GameObject is destroyed, the next time the event is triggered, most likely a crash will occur. A possible way to avoid this is to make your event handler static or to call DontDestroyOnLoad in your GameObjects script. Finally, delegates are primarily used when you want to know some information, but it will take time for OpenFeint to retrieve it from the servers. For example, if you want to determine if the current local user is following any other OpenFeint iOS users, you will need to supply a delegate function that will get called once OpenFeint has completed its query to the servers.

C# Example:

// Method signature must match that of the FollowingResultDelegate.
private void MyFollowingResultHandler(bool success, bool isFollowingAnyone) {
	if(success)   	{
        	if(isFollowingAnyone) {
			Debug.Log("Awesome\! He has friends.");
		}
	        else {
			Debug.Log("He lives a sad lonely existence.");
		}
    	}
	else {
		Debug.Log("The server request failed.");
	}
}
...
OpenFeint.IsLocalUserFollowingAnyone(MyFollowingResultHandler);

Javascript Example:

// Method signature must match that of the FollowingResultDelegate.
function MyFollowingResultHandler(success : bool, isFollowingAnyone : bool) {
	if (success) 	{
		if (isFollowingAnyone) 		{
			Debug.Log("Awesome! He has friends.");
		}
		else {
			Debug.Log("He lives a sad lonely existence.");
		}
	}
	else {
		Debug.Log("The server request failed.");
	}
}
...
OpenFeint.IsLocalUserFollowingAnyone(MyFollowingResultHandler);

The MyFollowingResultHandler will be called whenever a result is received from the OpenFeint iOS call. That should give you a general run-down of the different ways you can communicate with OpenFeint from Unity script.

Implementing challenge support in your Unity project

Adding challenges to your Unity game can add an extra layer of depth to your gameplay. The following is a discussion on how to implement challenge support into your Unity project, and some information on things you should be aware of while implementing challenges. Challenge data When you begin implementing challenge support, you need to determine what format your challenge data will be in. Two challenge data formats are supported by the OpenFeint Unity iPhone plugin: PlayerPrefs key data and file data.

With PlayerPrefs key data, you store the challenge information in a PlayerPrefs key or set of keys. These keys will get packaged up and sent as the challenge data to players upon sending a challenge, and unpackaged and stored upon starting a challenge. With file data, a file is sent as the challenge data instead. For the most part, file data will primarily be used by Unity iPhone Advanced licensees (as serialization is not available for Unity iPhone Basic licensees at this time). We will be discussing the PlayerPrefs key data method in this discussion, though the instructions should match fairly one-to-one with the file data method. Lets say that you want your challenge to consist of the players score and time on a level. You might then have two PlayerPrefs keys for each of these stats:

PlayerPrefs.SetInt("ChallengeScore", playerScore);
PlayerPrefs.SetFloat("ChallengeTime", playerTime);

These keys (ChallengeScore and ChallengeTime) will be sent to the various challenge methods in OpenFeint.cs. Sending a challenge When you are ready for the player to send a challenge, youll want to display OpenFeints iOS send challenge modal, and provide it with the challenge data that will be sent to players who accept the challenge. The DisplaySendChallengeModalWithPlayerPrefs method is what well be using to accomplish this. You can use it like this:

string challengeText =
    "Score more than " + playerScore + " points in under " + playerTime + " seconds.";
string[] challengeKeys = new string[] { "ChallengeScore", "ChallengeTime" };
OpenFeint.DisplaySendChallengeModalWithPlayerPrefs(
    myChallengeId, challengeText, challengeKeys);

Notice how we created a string array with the PlayerPrefs challenge key data that we wanted to send as part of the challenge. This method on brings up the send challenge modal, but doesnt give you any indication of whether the user sent a challenge or not. To get that information, youll need to subscribe to the OnUserSentChallenges and OnSendChallengeScreenClosed events. Be sure to unsubscribe from these events when youre finished with them. Playing a challenge Once that challenge has been sent to another player, that player can then accept the challenge and begin playing it. To be notified when the player wants to play a challenge, subscribe to the OnStartedChallenge event. When this event is triggered, it will send the challenge definition so youll have some basic information about the challenge immediately. However, it will NOT supply you with the challenge data itself. To get that, youll need to do something like the following:

string[] incomingChallengeKeys = new string[] { "IncomingChallengeScore", "IncomingChallengeTime" };
OpenFeint.GetChallengeDataToPlayerPrefs(incomingChallengeKeys);

Once GetChallengeDataToPlayerPrefs is called, the IncomingChallengeScore and IncomingChallengeTime PlayerPrefs keys will be populated with the challenge data that was received from the player who created the challenge. NOTE: When the player starts a challenge, some challenge information (including the challenge data) is automatically serialized to a file. Due to this serialization, if the player quits your game during the challenge and then later starts the app again, you can simply call GetChallengeDataToPlayerPrefs again to retrieve the challenge data. Youll need to track whether the player was in a challenge or not yourself though. When the player has finished playing the challenge, youll need to submit the challenge result to OpenFeint iOS.

OpenFeint.SubmitChallengeResult(
  OpenFeint.eChallengeResult.RecipientWon,
  "Scored " + playerScore + " points in " + playerTime + " seconds.");

You may also display the challenge complete modal by calling DisplayChallengeCompletedModalWithPlayerPrefs. You must do this if you want the player to send his challenge result as a re-challenge. You can track when the player closes the modal with the OnCompletedChallengeScreenClosed event. OnUserSentChallenges gets sent if the player sends a re-challenge. You should also subscribe to the OnRestartedChallenge event if you allow for multi-attempt challenges.

Implementing network save card support in your Unity project

You can also implement network save card functionality in your Unity project. This allows you to save information about a players game to OpenFeints servers (the cloud), in essence allowing that user to continue their game from any of their devices. Blob data Network save card information is stored in data blobs. One way to think of data blobs is that theyre like files where you store information about your players progress through your game. When you want to save some player information to the cloud, youll want to upload a blob. Much like challenge data, blob data can be uploaded (and downloaded) in two different formats: PlayerPrefs key data or file data. Read the information about challenge data above for more on this. Uploading blob data Uploading a blob to the cloud is really simple. See the following:

string[] blobDataKeys = new string[] {
   "PlayerName", "PlayerLevel", "PlayerExperiencePoints", "PlayerItems" };
OpenFeint.UploadBlobFromPlayerPrefs(
   "PlayerStats", blobDataKeys);

Just as with setting up the challenge data, you create a string array of PlayerPrefs keys and pass that to UploadBlobFromPlayerPrefs. Notice that you also set a key name for this blob. This means that you can upload multiple blobs for a single player. Downloading blob data Downloading blob data is simple as well. See the following:

private void DownloadedBlobResultCallback(bool success)
{
	if(success) {
		Debug.Log("Downloaded blob from the cloud\!");
	}
	else	{
		Debug.Log("A problem occurred while downloading the blob from the cloud.");
	}
}

string[] blobDataKeys = new string[] { "PlayerName", "PlayerLevel", "PlayerExperiencePoints", "PlayerItems" };
OpenFeint.DownloadBlobToPlayerPrefs("PlayerStats", blobDataKeys, DownloadedBlobResultCallback);

Calling DownloadBlobToPlayerPrefs initiates the download from the cloud. Then the callback function supplied to the third parameter is called upon success or failure of the download.