Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Unity plugin to handle loading native Cocoa UI's with ease

Discussion in 'iOS and tvOS' started by prime31, Aug 8, 2010.

  1. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    First off, thanks to Gregg Patton and his blog post for inspiring this plugin. This has only been tested with Unity 3 beta. Second, all relevant code is available on GitHub. The relevant folders are NativeBinding, NativeCode and for a test project look in the TestScenes folder.

    This plugin makes it dead easy to integrate UIKit with Unity for pause menus, level selection, cut scene navigation, etc. UIKit makes creating menu systems and settings panes a breeze compared to in Unity and this plugin aims to fill the gap.

    The basic gist of the usage is really simple and flexible. You can either go with all the defaults for the UnityNativeManager or in your Xcode project just set them once and they will hold for the duration of the game. The interesting properties and methods for customizing the animations are:

    Code (csharp):
    1. CAMediaTimingFunction *animationTimingFunction // available options are the usual bag: easeIn, easeOut, easeInOut, easeOutIn
    2. CFTimeInterval animationDuration; // duration of the animation
    3.  
    4. // set the specific animation (and subtype if applicable).  See the header for all available types and subTypes.
    5. - (void)setAnimationType:(NSString*)animationType subtype:(NSString*)animationSubtype;
    From Objective-C, you can easily call a few built in methods or add your own. The UnityGameController.cs script has some common methods callable from Obj-C such as: loadLevel, loadLevelAdditive, loadLevelAsync, loadLevelAdditiveAsync. All you need to do to load a level additive async from Obj-C is the following:

    Code (csharp):
    1. [[UnityNativeManager sharedManager] pauseUnity:NO];
    2. UnitySendMessage( "UnityGameController", "loadLevelAdditiveAsync", [@"PartialScene" UTF8String
    ] );


    From the Unity side of things all you need to do to get a viewController up and running is call the following method:

    Code (csharp):
    1. UIBinding.activateUIWithController( "TestViewController" );
    If your view controllers are setup with nib files this will take care of instantiating them with the nibs. It will also take care of pausing Unity and animating the view controller in. To dismiss the view controller and unpause Unity just call:

    Code (csharp):
    1. [[UnityNativeManager sharedManager] hideViewControllerAndRestartUnity];
    For anyone who knows a bit about Cocoa/Objective-C or anyone willing to learn just the very basics this will make creating really nice menu systems a breeze.

    Enjoy!
     
    Last edited: Oct 4, 2010
  2. EskemaGames

    EskemaGames

    Joined:
    Jun 23, 2010
    Posts:
    319
    This is really good stuff, and coded in obj-c :D ,we both know some guy who will be mad for use obj-c instead of plain C hehehehe
     
  3. liquidgraph

    liquidgraph

    Joined:
    Feb 26, 2009
    Posts:
    324
    Does this only work with Unity iPhone Advanced? Or basic too? Where can I get more info about how to actually construct the menues/buttons? How much objective-C knowledge does that require?
     
  4. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    in unity iphone 1.x native plugins are advanced only, in unity iphone 3 in both
     
  5. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    It's actually pretty simple. You can use the drag-n-drop GUI editor Interface Builder to make the GUI. Apples docs are the best around and all you really need to learn is very basic Interface Builder and IBActions to get a menu rolling.
     
  6. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    Thanks uprise78,


    I found these two Apple Developer WWDC 2010 session videos pretty interesting to show what can be done with UIKit and Games.

    The iPad sample uses UIKit

    Game Design and Development for iPhone OS, Part 1 and 2 - WWDC 2010 (they are free via iTunes but you need to be a registered Apple developer to view)

    iByte
     
  7. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Thanks! I've been wondering how hard this would be.

    I suspect I'm just being stupid, but can you post the .nib you used with the sample scene? I can run it on hardware and get the "got touch" messages to the console, but it doesn't instantiate the viewController I created named "TestViewController".

    EDIT: Never mind, I found it. Is it supposed to be automatically including the NativeCode assets into the XCode project? I had only added the stuff from the top level NativeCode folder, which doesn't include the .xib or TestViewController class.
     
  8. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    I should have mentioned that after the first time you build your Unity app you will need to drag the NativeCode folder from Unity to Xcode. From then on, just do an append when you build. Another good one for Universal apps is just append "-pad" on to the nib name and you get automatic iPad nib loading when on an iPad.

    For example, if you have a view controller named TestViewController you would create TestViewController.xib for the iPhone and TestViewController-pad.xib for the iPad. Nothing else needs to change to load up the iPad interface. HUGE timesaver to say the least.
     
  9. Hungariano

    Hungariano

    Joined:
    Mar 24, 2009
    Posts:
    60
    Hi,
    I have tried your code and it looks great but I have ran into a small problem. I am very new to objective-c and i find it a bit hard to learn, but I am getting there :)

    I would like to have my GUI in landscape mode only, how would I go about that?

    Hope you can give me some pointers.
     
  10. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    I ran into this myself and (finally) seem to have it working for landscape with some changes.

    I'm not 100% sure all of these are required, so others should chime in.

    The view controller class needs to tell the system it supports landscape mode:
    Code (csharp):
    1.  
    2.  
    3. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    4. {
    5.     return UIInterfaceOrientationIsLandscape(interfaceOrientation);
    6. }
    7.  
    I also needed to replace the entire window, rather than just add the view, because (I think) the OpenGL view was stealing the rotation messages. I changed UnityNativeManager showViewControllerWithName: and hideViewControllerAndRestartUnity: to call [UIWindow makeKeyAndVisible] and swap the Unity Window and my new window.
    Code (csharp):
    1.  
    2.     _nativeWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    3.     _unityWindow = [UIApplication sharedApplication].keyWindow;
    4.     [_nativeWindow makeKeyAndVisible];
    5.     UIWindow *window = _nativeWindow; //[UIApplication sharedApplication].keyWindow;
    6.  
    Of course swapping the window means the entire screen is your UIKit view. I'd really like to be able to layer a UIKit view over Unity as well - has anyone gotten this to work in landscape mode?
     
  11. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    I dont have Unity at this computer but something like the following might work:

    Code (csharp):
    1. [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft animated:NO];
     
  12. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    I couldn't get any combination of
    Code (csharp):
    1.  
    2. [[UIApplication sharedApplication]setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft animated:NO];
    3.  
    or
    Code (csharp):
    1.  
    2. SetScreenOrientation((ScreenOrientation)UIInterfaceOrientationLandscapeLeft);
    3.  
    to work.

    But I'd love to be wrong if somebody can figure out what's going on. Like I mentioned above, I suspect the OpenGL view is keeping it from rotating as described in

    Technical Q&A QA1688
    Why won't my UIViewController rotate with the device?
     
  13. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    I remember having this issue as well now. All you need to do to fix it is wrap the EAGLView in a view controller. An example would be something like this:

    In the function OpenEAGL_UnityCallback remove/comment out the line:
    Code (csharp):
    1. //[_window addSubview:view];
    Add the following 3 lines:
    Code (csharp):
    1. // Instantiate a view controller
    2. UIViewController *vc = [[UIViewController alloc]
    3. init];
    4. [vc.view addSubview:view];
    5. [_window addSubview:vc.view];
    That code will ensure that the EAGLView is wrapped in a view controller which should get the shouldAutorotateToInterfaceOrientation: called on all the view controllers.
     
  14. Hungariano

    Hungariano

    Joined:
    Mar 24, 2009
    Posts:
    60
    Thanks for the feedback. I have tried to solve it myself using - (BOOL)shouldAutorotateToInterfaceOrientation: and such but with no luck.

    I had a suspicion that it might have something to do with the EAGLView but my lack of knowledge stopped me from getting any further.

    I will however try your suggestions and report back.
     
  15. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    autorotation can be applied to extra stuff you put on top, unity won't do it and you can't get it to do it without major problems and reworks in your application to handle rotations, coordinate system issues etc.
     
  16. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    If I recall, Unity works fine when you allow the EAGLView to autorotate inside a view controller. The passed touch coordinates are exactly the same for landscapeLeft/Right. It doesn't work when you rotate views on top of or manually change the transform of the EAGLView.
     
  17. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    So, I finally got back to my machine with Unity on it and got landscape views working perfectly. I pushed updated code and an updated test package: on github

    The only difference is you have to include the CoreGraphics framework and the viewControllers views will automatically be set to the orientation of the device.
     
    Last edited: Oct 4, 2010
  18. Hungariano

    Hungariano

    Joined:
    Mar 24, 2009
    Posts:
    60
    That sounds great :)
    I will download and try now in the morning.

    Thanks for help.
     
  19. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Great, that brings me up in the correct orientation.

    I'm sure I'll still have ugly issues related to rotation, but thanks again for figuring this stuff out. This would all be a lot simpler if the Unity EAGLView just played well with others, I wonder if they could be convinced to do that for Unity3...

    I did change the transforms, just because I thought it was a tiny bit tidier.
    Code (csharp):
    1.  
    2.     // If we are landscape, manually rotate our view
    3.     if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft )
    4.         controller.view.transform = CGAffineTransformMake(0, -1, 1, 0, 0, 0);//CGAffineTransformMakeRotation( -1.5708 );
    5.     else if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight )
    6.         controller.view.transform = CGAffineTransformMake(0, 1, -1, 0, 0, 0);//CGAffineTransformMakeRotation( 1.5708 );
    7.  
    8.  
    Edit:
    I put in a feature request about the view being more UIKit friendly.
    Possible EAGLView improvements
     
  20. patrickoshaughnessey

    patrickoshaughnessey

    Joined:
    Apr 24, 2008
    Posts:
    1
  21. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @patrickoshaughnessey, thanks for the heads up. I just updated all the appropriate links.
     
  22. fousa

    fousa

    Joined:
    Sep 30, 2010
    Posts:
    1
    How can automatically load the UIViewController when starting my application?
     
  23. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @fousa, you just need to activateUIWithController as soon as your game is loaded.
     
  24. damien

    damien

    Joined:
    Jun 17, 2009
    Posts:
    32
    Can I use this to popup a native alert?
     
  25. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @damien, not as is. That's isn't it's purpose. It is designed to display entire view controllers.
     
  26. Sirithang

    Sirithang

    Joined:
    Nov 29, 2010
    Posts:
    28
    Hi!

    Sorry to post there but i'm trying to use your plugin and i have a few question (i'm really really new to Objective-C)

    I see in the souce code that it instancies a "UIVIewController". But what i'm trying to do is a Navigation Controller based app, is this possible? I know that its not directly related to the plugin, but well, this is kinda hard for me....

    If i juste change the "UIViewController" by a UINavigationControler, will it work? Because you already encapsulated it in a Navigation Controller...


    Since i'm new to Obj-C and iOS SDK, it's hard for me to do something, since every tutorial use an AppDelegate and such thing, programm of their own, and not just a ViewController to put in Unity...

    Sorry if I'm not very clear, i'm a bit lost here, and my english could use a serious improving ^^"...
     
  27. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @Sirithang, before embarking on the journey you are attempting to embark upon, become at least mildly proficient in making standard iOS apps. There are thousands of tutorials out there on the web to get you going. Just about every tutorial will have a UIViewController running the show and all the AppDelegate does it create the view controller and insert into the window so you can ignore that.
     
  28. Spookytooth

    Spookytooth

    Joined:
    Jun 27, 2009
    Posts:
    57
    @Prime31, Thanks for doing the dirty work on this, and thanks to Gregg for the blog post. We are working on this very thing, and I do hope we don't need too much help after going through all the tutorials you guys have put together. I'll keep you posted! Thanks again for all the great tools and info. Cheers!
     
  29. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    Hello,
    well was curious and test some stuff with this...
    so i always get this error and did not know whats wrong ?
    any idea what's wrong ?
    many thanks
     
    Last edited: Jan 25, 2011
  30. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    You need to add the CoreGraphics.framework to your project
     
  31. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    Superb! works fine... but when i rotate my phone the gui looks not fine...
    what can i do to make it better rotating with the iPhone ?
    mercy
     
  32. iguana_02

    iguana_02

    Joined:
    Apr 22, 2011
    Posts:
    211
    Hi, i think i'm in the right place to ask this question.
    First this is my first post ever so...a big HELLO to everyone here!

    I'm completely new in unity3d, xcode and Objective C programming so you can understand my problem, i'm studying very hard at least 8 hours a day to learn as much as i can.

    And now, straight to the point:
    I did a minigame on unity3d, everything works fine, fast and clean and its very fast and fluid on the iphone, my only (BIG) problem is that i need to do the GUI in xcode.
    My first idead was just to create UI using interface builder but its not working...and then i found Native toolking that according to the info should be exactly what i need.
    The problem is...due to my lack of programming i don't understand how to make it work...i need and "Idiot proof step by step tutorial"...
    Or at least a small help.

    My project need only a main menu with 3 choices (play, info,credits) i thought was easy hehehehe...

    Thank you!!!
    Ale.

    Anyone
     
  33. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    Hi iguana. Have a look at the demo scene that comes with the plugin. It demonstrates setting up a button to load a specific level. You can use that as a template to add your other buttons for the other levels and you should be good to go.
     
  34. iguana_02

    iguana_02

    Joined:
    Apr 22, 2011
    Posts:
    211
    WOW! That was a fast response!
    I'll check in a mo!
    I think my main problem is that i didn't understand the pipeline to use.
    For example:
    1) create my unity3d scene
    2) Export to xcode
    3) modify xcode to add cocoa interface

    or

    1) create cocoa interface
    2) export data for unity
    3) add interface to unity
    4) export for xcode and compile.

    or something completely different...don't know.

    Prime31, you know my main problem is that i just started this "adventure" (actually i'm a visual effects artist)...

    Thank you for your help! This is an incredible community...:)

    EDIT: I tried to publish the scene and xcode reports 10 errors during build,
    EDIT2: i found why it doesn't work...its a PostprocessbuildPlayer i tried with terminal with the command: chmod a+x PostprocessbuildPlayer* but nothing happens...but anyway i think once i solved this one it's done.
     
    Last edited: Apr 24, 2011
  35. macfinch

    macfinch

    Joined:
    Aug 24, 2010
    Posts:
    139
    Hey Prime, hope you're doing well man.

    I wanted to ask a quick one on your post above. I'm trying to implement a 3rd party library which is written in obj-C and I'm using the 'wrap the EAGL view in a UIViewController' technique you mentioned. One of the function calls I need to make from Unity is to display a pre-written email on the iPhone using the default email app. The problem is that when I make the function call DisplayNewsLetter() and pass it the RootViewController from within AppController.mm, the email screen doesn't pop-up. I'm pretty sure it's executing the code but it looks like it's just not appearing in front of the Unity window. Here's the code I'm using:

    //inside AppController.mm
    [NewsletterLibrary displayNewsletter: _window.rootViewController];

    Do you know if I need to call some kind of ShowWindow() / BringToFront() command? or is it because it needs to have a xib file associated to the main Unity window?

    Thanks in advance for any advice.
    All the best.
    - M
     
  36. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @Macfinch, I haven't a clue. You shouldn't need to do any trickery to get anything to work. Use the GBB console and debugger to see what is happening just like you would do with a non-Unity app.
     
  37. macfinch

    macfinch

    Joined:
    Aug 24, 2010
    Posts:
    139
    Hi Prime, thanks for the reply. Will give it a try and let you know how I get on.

    Thanks
    - M
     
  38. pion

    pion

    Joined:
    Jul 7, 2011
    Posts:
    27
  39. jsr2k1

    jsr2k1

    Joined:
    Aug 11, 2010
    Posts:
    118
    @Prime31: Hello, I want to open a PDF file from Documents folder using activateUIWithController from the Native Toolkit, but I can't.

    I can open the file from Data folder with this code:
    Code (csharp):
    1.  
    2. // the 'file' is: [..]/MyApp.app/Data/Raw/_Data/MyPDF_Folder/MyPdf.pdf
    3. string baseFile = file.Substring(file.IndexOf("Data/Raw/"));
    4.  
    5. baseFile = Path.GetDirectoryName(baseFile) + "/" + Path.GetFileNameWithoutExtension(file);
    6. // the 'baseFile' is: Data/Raw/_Data/MyPDF_Folder/MyPdf
    7.  
    8. PlayerPrefs.SetString("DocViewerFileName", baseFile);
    9. PlayerPrefs.SetString("DocViewerType", Path.GetExtension(file).Substring(1));
    10. PlayerPrefs.SetFloat("DocViewerX", currentImageX - m_scrollViewArchivos.ScrollPosition.x + image.width * .5f);
    11. PlayerPrefs.SetFloat("DocViewerY", m_rectScrollPositionArchivos.y + image.height * .5f);
    12.  
    13. NativeToolkitBinding.activateUIWithController("ipadDocOpenerViewController");
    14.  
    Is it possible to access the file from Documents folder instead of Data folder?

    Joel
     
    Last edited: Sep 12, 2011
  40. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @jsr, you can absolutely open a PDF from either location. Your question would have a much better chance of being answered on an iOS specific forum (not a Unity forum).
     
  41. alejobrainz

    alejobrainz

    Joined:
    Sep 10, 2005
    Posts:
    288
    Prime31,

    I want to activate a view that contains a uiwebview. Is there an easy way to pass a parameter from Unity to the native view (e.g.. the url for the web view to launch)?

    Alejandro
     
  42. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @Alejandro, see the classes that come with the plugin for examples. There is no really "easy" way to do anything when you have to cross back and forth from native to managed code but it is all possible.
     
  43. iguana_02

    iguana_02

    Joined:
    Apr 22, 2011
    Posts:
    211
    Hi Prime, i just downloaded the latest version of NativeToolkit and now it works fine on 3.4 but i notice a problem (could be a bug).

    If i click the home button (or i receive an sms or phonecall) while i'm on a IB menu everything is fine and i can click on the game and go back.

    If i click on the home button (or other events) while i'm on the game (the unity only ogl window) when i click back to the game its still paused and there is nothing i can do except delete the app and re install it.

    I tried to put on applicationDidBecomeActive , [self pauseUnity:NO]; and it works but obviously unity is running always even if i am on an IB menu (i can hear the music and sound effects).

    Any solution?

    Thanks

    Iguana
     
  44. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @iguana, you will need to get a bit tricky and pause/unpaide at the appropriate time based on whether you have a ViewController visible or not.
     
  45. iguana_02

    iguana_02

    Joined:
    Apr 22, 2011
    Posts:
    211
    i will try this way, i was just wondering because with the previous version it was working fine but i gues its because of the new unity wrap mode.

    Thank you man!
     
  46. btiger19

    btiger19

    Joined:
    Jun 28, 2009
    Posts:
    56
    Hi Prime31, the Native UI plug-in is very easy to use and is it possible to call tab bar controller by this plug-in?
     
  47. ks32

    ks32

    Joined:
    Oct 27, 2010
    Posts:
    6
    @prime31

    Your plugin is great. But its no longer working after I inserted custom function in NativeToolkitManager.css and in NativeToolkit.mm. Let me know if NativeToolkitManager.css/NativeToolkit.mm cannot be modified.
     
  48. ks32

    ks32

    Joined:
    Oct 27, 2010
    Posts:
    6
    oops! it was my fault. There was a bad file name (readme.md) present in my xcode files which was causing the problem.

    It is working fine with modifications.
     
  49. noelrocha

    noelrocha

    Joined:
    Dec 2, 2011
    Posts:
    1
    Hi,

    I would like to know how to open (from Unity) a UIViewController that is created programmatically.

    I don't like to use Interface Builder.

    Thanks
     
  50. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @noelrocha, IB isn't a requirement. The process is the same whether you use xibs or not.