Skip to: Site menu | Main content

Unity iPhone Enhancement

The Unity iPhone Enhancement Pack is turning 1.5. There's lots of new features.






This enhancement for Unity iPhone adds a number of features to the engine via Objective-C. Sure, none of this is rocket science, and yes, lots has already been shown on the Unity forums. (Even some sample code from me!) The point of offering this for sale is to provide a complete, all in one package for these enhancements, without requiring knwoledge of Objective-C.


Available Functions

By default, the enhancement pack supports a second splash screen (to help make the load times seem shorter).

On-Screen Keyboard

Display the standard iPhone keyboard for text entry. Recieve a line of input, or individual keystrokes.

Play Video

Playback videos, either from inside your application bundle, or from the internet. You can choose to display or hide the standard movie controls.

Camera and Photo Gallery

The user can take a picture with the camera, or pick a photo from the photo gallery, and have it be used inside the game. Here's the photo gallery:

...and that photo used inside the game:

Second Splash Screen

To help reduce the perceived wait time, the Enhancement Pack automatically will show a second splash screem, if you include one in your project. The screen is faded in with a nice CoreAnimation effect. This is optional -- if you don't want a second screen shot, simply don't include it in your project, and the code will skip it.

AdMob Support

You can display an AdMob view over the top of your game. Simply pass in your AdMob publisher ID and the orientation you want the ad to appear in. The Enhancement Pack support landscape (right) and portrait (top).

CoreLocation

Start CoreLocation to receive updates about the iPhone's latitude, longitude, and altitude. You can also stop CoreLocation when it's no longer needed, to save memory and battery power.

Enhancement Pack 1.5 Function List

 // Getting Results of Deferred Actions

string SB_getNextResult();
int SB_getResultCount();

// Camera

void SB_takePicture ( string texSize );
void SB_takeVideo ();
void SB_photoPicker ( string texSize );

// AdMob

void SB_showAdMobView ( string pubId ); 
void SB_hideAdMobView ();
void SB_setAdMobTestMode ( bool mode );

// Screenshot

void SB_screenshot();
void SB_screenshotToFile();
void SB_screenshotDeferredSave ();
void SB_screenshotPerformDeferredSave( string destination );

// Web View

void SB_openWebView ( string url, bool fullscreen );

// Alerts

void SB_alert (string title, string msg, string btn1, string btn2 );
int SB_modalAlert (string title, string msg, string btn1, string btn2 );

float SB_getMemoryFree();
float SB_getMemoryUsed();
float SB_getMemoryTotal();

// Compass

void SB_startLocationManager();
void SB_stopLocationManager();
float SB_trueHeading();
float SB_magneticHeading();

string SB_getDeviceModel();

// iPod Control

void SB_ipodPickAndPlay();
void SB_ipodPlay();
void SB_ipodPause();
void SB_ipodStop();
string SB_ipodGetNowPlaying();
float SB_ipodGetVolume();
void SB_ipodSetVolume(float v);
int SB_ipodGetPlaybackState();

// Email Composer

void SB_composeMail ( string to, string subject, string message);
void SB_composeMailHtml ( string to, string subject, string message);

// StoreKit

bool SB_startStoreKit();
void SB_getProductData( string products ); 
void SB_purchaseItem( string itemId, int qty);
void SB_validateReceipt( string receipt, bool testMode );

// Flurry

void SB_flurryStart(string apiKey );
void SB_flurryLogEvent( string event_string );
void SB_flurryLogError( string errName_string, string errMessage_string );
void SB_flurryRegisterExceptionHandler();
void SB_flurryTestCrash();

// FaceBook Connect 

void SB_facebookStart( string apiKey_str, string myAppSecret_str );
void SB_facebookLogout();
void SB_facebookPublishFeed( string feed_str);
void SB_facebookGetPermission( string perm_str );
void SB_facebookSetStatus (string status_str);

// TV Output

void SB_startTVOut();
void SB_stopTVOut();


// Deprecated Functions

playVideoUrlWithControls
playVideoWithControls
vibrate


OpenFeint
void SB_showOpenFeint();
void SB_submitScore(int score, string board_str);
void SB_startOpenFeint( string key_string, string secret_string, string appName_string, int orientation);
void SB_stopOpenFeint();

Scoreloop
void SB_scoreloopStart( string apiKey_str, string myAppSecret_str );
void SB_scoreloopShow( int tab);
void SB_scoreloopSubmitScore( int score, int level );
string SB_scoreloopGetOpponent();
string SB_scoreloopGetStake();
void SB_scoreloopContextSetProperty( string name_str, string value_str );
string SB_scoreloopContextGetProperty( string name_str );

Audio Recording
string SB_startMicRecording(string filename);
void SB_stopMicRecording();
float SB_getMicPeakLevel();
float SB_getMicAvgLevel();
float SB_getMicPeakLowPassFiltered();

Hands-Free XCoding

Don't know Objective-C or XCode? Don't worry. You don't have to do anything in XCode. The PostprocessBuildPlayer script fires off a bunch of AppleScript commands to XCode to add the new files and frameworks to the project. And your Default.png, Icon.png and any other assets (i.e. videos) are copied over and added to the project, too.

If you are using Unity seriously for iPhone development, this script is worth the price of admission all by itself.

Note: You do have to set your code-signing entity. The AppleScript removes any additional tedium, but doesn't eliminate alltedium.

Caveats

Intra-engine communication happens through PlayerPrefs. These calls aren't atomic. i.e. After you call "getInput", you can't be sure that the "sb_result" will exist immediately after the engine is unpaused. In a world without direct function calls and return values, you have to write your code to be a little more forgiving. I know it's imperfect, but hey, it works today.

Sample Code

Thanks to Jonathan Czech for the code to load the texture from the sandbox file.


function OnGUI () { 
   var s:String;
   var fname;
   if (GUI.Button (Rect (10,10,160,40), "Play Video (http)")) { 
      PlayerPrefs.SetString("sb_command", "playVideoUrlWithControls|http://robterrell.com/coraline-movie-trailer.mp4"); 
   }
   if (GUI.Button (Rect (10,60,160,40), "Play Video (bundle)")) { 
      PlayerPrefs.SetString("sb_command", "playVideoWithControls|coraline-movie-trailer.mp4"); 
   } 
   if (GUI.Button (Rect (10,110,160,40), "Show Ad")) { 
      PlayerPrefs.SetString("sb_command", "showAdMobView|a149832df60b780|lanscape");
   } 
   if (GUI.Button (Rect (180,110,160,40), "Hide Ad")) { 
      PlayerPrefs.SetString("sb_command", "hideAdMobView");
   } 
   if (GUI.Button (Rect (10,160,160,40), "Get Location")) { 
      PlayerPrefs.SetString("sb_command", "startLocationManager"); 
   } 
   if (GUI.Button (Rect (10,210,160,40), "Take Picture")) { 
      PlayerPrefs.SetString("sb_command", "takePicture"); 
   } 
   if (GUI.Button (Rect (10,260,160,40), "Get Input")) { 
      PlayerPrefs.SetString("sb_command", "getInput");
   }
   if (GUI.Button (Rect (180,260,160,40), "Get Keys")) { 
      PlayerPrefs.SetString("sb_command", "getKeystrokes");
   }
   if (GUI.Button (Rect (180,210,160,40), "Show Gallery")) { 
        PlayerPrefs.SetString("sb_command", "photoPicker"); 
   }
   s = PlayerPrefs.GetString("sb_result"); 
   if (s != "") GUI.Label(Rect(280,10,190,200), "Result: " + s);
   if (PlayerPrefs.GetFloat("sb_longitude") != 0) GUI.Label(Rect(380,260,100,20), "lng: " + PlayerPrefs.GetFloat("sb_longitude"));
   if (PlayerPrefs.GetFloat("sb_latitude") != 0) GUI.Label(Rect(380,280,100,20), "lat: " + PlayerPrefs.GetFloat("sb_latitude"));
   if (PlayerPrefs.GetFloat("sb_altitude") != 0) GUI.Label(Rect(380,240,100,20), "alt: " + PlayerPrefs.GetFloat("sb_altitude"));

	if (s.IndexOf("/var/mobile/Applications/") > -1) { 
       	fname = PlayerPrefs.GetString("sb_result");
        Debug.Log("file is " + fname);
		LoadImageIntoRenderer(fname);
		PlayerPrefs.SetString("sb_result", "");
 	}
}

function LoadImageIntoRenderer(path) { 
      if (renderer == null || renderer.material == null) { 
         Debug.Log("LoadImageIntoRenderer needs renderer and material"); 
         return; 
      }

      Debug.Log("Attempting to load texture "+ path); 
      var fs = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read);
      var thebytes = new byte[fs.Length];
      fs.Read(thebytes, 0, fs.Length);
      var texture = new Texture2D(1,1);
      texture.LoadImage(thebytes);
      renderer.material.mainTexture = texture;
}

Compatible

The Unity iPhone Enhancement pack strives to remain compatible with future Unity upgrades. It does this in the following ways:

What If?

There's a good chance that a future release of Unity will incorporate some (or all!) of these features. (It's already happened -- since the Enhancement Pack first came out, Unity added video playback, vibration, and an on-screen keyboard.) If that worries you, don't buy it! This is for developers creating games with Unity right now, who need to get something working today. Or developers who wants to see how things get done in Objective-C.