Unity iPhone Enhancement
Enhance Unity for iPhone to support new features.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).
- WebView: shows a live web view over your game. You can show the view fullscreen, or inset it slightly. You can add links to the page that send strings back to Unity. No need to quit your game and open Safari to show a high scores list!
- StoreKit: get product data from iTunes, make purchases, and validate receipts!
- iPod: control the iPod's playback, let the user select tracks to play, get the iPod state, set or get the iPod volume.
- Email: presents an email composer window, allowing the user to send an email from within your game.
- FaceBook Connect: support for connecting to FaceBook, setting a user's status, and making a wall posting.
- Flurry: support for the Flurry app analytics API.
- CoreLocation and stopCoreLocation: turn on or off CoreLocation updates, including Compass data on the 3GS.
- showAdMobView() and hideAdMobView(): show, hide, or refresh an AdMob ad view
- takePicture() and takeVideo(): open a camera view and lets the user take a picture or video with the camera; saves it as a file in the application's Documents directory, and returns the path to the file.
- photoPicker: shows the photo gallery and lets the user select a photo; saves it as a PNG in the application's Documents directory, and returns the path to the file.
- photoPicker: shows the photo gallery and lets the user select a photo; saves it as a PNG in the application's Documents directory, and returns the path to the file.
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:
- Categories. The functionality is implemented as a category, that is to say, methods added to the base AppController class. The original Unity code remains untouched. As Unity updates your XCode project with newer versions, the EP and Unity code remain separate. No confusion, no merging.
- Communication. For Unity Basic, the functionality is implemented by passing strings and other data between the Objective-C and Unity script layers through the user preferences.
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.