Search Unity

Unity AppController subclassing.

Discussion in 'iOS and tvOS' started by techmage, Jul 23, 2013.

  1. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    So in 4.2 there is this release note:

    iOS: Improved support for AppController subclassing and unity view integration with native UI.

    I am someone who pretty much hacked the AppController like two years ago to get it integrated with Native Apps, and have just been running on my own method, which works, but is a little hackie.

    So it seems like doing this now is a bit more supported?

    Also it says 'integration with Native UI', does this mean the actual Unity view can be moved around and placed, as a smaller window in Native UI?

    I would really like to see some official example code on all the best methods to do this.
     
  2. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    well, it depends, but thats our goal sure. 4.2 was mainly about ui integration

    yep

    we are working on updating our "learn" site with samples of new 4.2 features
     
    Jessy likes this.
  3. jondbell

    jondbell

    Joined:
    Dec 17, 2012
    Posts:
    4
    In case anyone else is struggling with this, this is what we did to get our old custom AppController functions to work with 4.2 (which may change depending on the best practices in the forthcoming documentation) since we had trouble just merging AppController into UnityAppController (it was deploying to the Libraries directory instead of the classes directory where we expected it to go and overwrite the default one).

    After building from unity, add a new subclass of UnityAppController in the Libraries directory of your XCode project. We called it CustomAppDelegate. In that class, add the functionality that you had before in AppController. It actually is quite nice to have this separate so you can see your custom functionality easier. Most of ours are just a couple extra lines and then call the methods on the super class. Once you have all that separated out into CustomAppDelegate.mm (you can leave CustomAppDelegate.h the way it is) then edit line 15 of main.mm to point to your subclass's name ("CustomAppDelegate" in our case). It should be working at this point, but run it just to make sure. Once you know it is running, copy main.mm, CustomAppDelegate.h and CustomAppDelegate.mm into your Plugins/iOS/ directory in your unity project and rebuild. Should be working now.
     
  4. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133

    Oh damn.

    Can you have multiple smaller Unity windows in the Native UI??????
     
  5. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    oh you can have it easier
    noticed IMPL_APP_CONTROLLER_SUBCLASS in UnityAppController.h? ;-) it does exactly that
    Actually you (more or less) described the process of doing custom AppController: subclass, override what you need, add define so yours is instantiated. And yes, we are prepping samples, just wait a bit

    hm, i dont think we support multiple unity views [because you will need ton of stuff to make it work], but on the other hand it is *kinda* doable (as in - rendering to separate views) - airplay works this way more or less. But as for integrating unity view - yes, you can have smaller unity view somewhere in your hierarchy.
     
  6. jondbell

    jondbell

    Joined:
    Dec 17, 2012
    Posts:
    4
    Ah, thanks, I didn't look for clues in UnityAppController.h so I missed the IMPL_APP_CONTROLLER_SUBCLASS #define. Looking forward to the samples. Thanks again.
     
  7. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    What does this do exactly, if you could explain. I am working on figuring this out right now.
     
  8. marjan

    marjan

    Joined:
    Jun 6, 2009
    Posts:
    563
    So is there then now a way to completely destroy unity? Or still only the Pause / unpause way.
     
  9. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    I doubt there is, and really wouldn't want to at all. I initially wanted to do this, but after understanding a bit more just about Mono in general and how it's supposed to work.

    After your app launches, it is then supposed to completely initialize the Mono core, and have mono running in the background, taking up an extra 5-8 mb of RAM. That is just the downside of Mono, which is pretty minor now, it's only 5-8 Mb. In MonoTouch you can't initialize your Mono library, use it, then at some point completely destroy the Mono instance running. Not supposed to be that way. Mono is intended to just be an additional, constant running layer on top of Objective-C in iOS app. Not in anyway is MonoTouch, and thus Unity, supposed to be something which can initialize and uninitialize like a seperate component of the app.

    Plus really, would you want to add an additional 2-4 seconds onto the load time to reinitialize the MonoCore and UnityEngine anytime someone loads a Unity scene? I wouldn't. I initially made it in my hybrid Native+Unity app that Unity didn't get initialized till first usage. But then I moved it to initialize in ApplicationDidFinishLaunching just because it's better to have that extra 2 seconds in the very begining of the app rather than once the user is in the UI and clicking around.

    What COULD be done is potentiailly the Mono and Unity core could be more intelligent in allocating and unallocating it's own resources. I don't know if it is or not. I suspect more could be done with this. Cause how much RMA is an empty unity scene now on iOS with full stripping? Isn't it like 12 MB? It'd be nice if when you loaded a scene, it kept track of what exactly it needed to put in memory and what it didn't. 12 MB for just the mono core and an empty unity scene does seem like too much.
     
  10. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    Is the documentation for this anywhere near complete ?
     
  11. elbows

    elbows

    Joined:
    Nov 28, 2009
    Posts:
    2,502
    Any news about documentation for this?
     
  12. aloschilov

    aloschilov

    Joined:
    Aug 19, 2013
    Posts:
    1
    Hi Alexey,
    please let me know where it is possible to get a simple sample application of using IMPL_APP_CONTROLLER_SUBCLASS. I am ok with rough and undocumented one.

    best regards,
    Alex.
     
  13. fraques

    fraques

    Joined:
    Aug 9, 2012
    Posts:
    8
    Hello. I'm trying to follow jondbell technique but I can't get it to work on my project, unfortunately.

    I have an application with two views on a storyboard. On the first view I want to display some custom content and a button that makes a push to the second view, where I put my Unity scene.

    But when I run the app I get a dark screen and Unity seems to fail initialization. I get the following error on the console

    How can I implement that so it will work? Any help or hint will be greatly appreciated. I'm new to Objective-C but I will dedicate all my time to this until I solve this issue.

    Thanks!
     
  14. fraques

    fraques

    Joined:
    Aug 9, 2012
    Posts:
    8
    Ok, so now I got Unity to initialize properly

    I had a custom ApplicationDidFinishLaunchingWithOptions method on my Custom App Delegate, so it was overriding the one in UnityAppController. To fix this you need to put

    Code (csharp):
    1. [super application:application didFinishLaunchingWithOptions:launchOptions];
    at the very beginning of the method. I guess every time you override a UnityAppController method, you will probably want to make a call to the corresponding super method so you will not loose any functionality. Now it is launching Unity fullscreen with no problems.

    So next step is loading my custom Storyboard. And here I'm stuck again.

    I tried this

    Code (csharp):
    1.  
    2. @interface CustomAppDelegate ()
    3. @property (nonatomic, strong) UIStoryboard *storyboard;
    4. @end
    5.  
    6. @implementation CustomAppDelegate
    7. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    8. {
    9.     //Call super method
    10.     [super application:application didFinishLaunchingWithOptions:launchOptions];
    11.    
    12.     //Init storyboard
    13.     self.storyboard = [UIStoryboard storyboardWithName: @"MainStoryboard" bundle: nil];
    14.     self.rootViewController = [self.storyboard instantiateInitialViewController];
    15.    
    16.     //Return
    17.     return YES;
    18. }
    19.  
    First it complained about the assignment of the rootViewController, so I removed the readonly flag of its property declaration in UnityAppController.h. Then I tried to run it and I got a SIGABRT error at launch.

    I will keep working on this. Any help or hint would be fantastic
     
  15. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    I second this.

    I am going to have to be upgrading all of our Unity 3.5 apps to Unity 4 in the next few weeks. Two of these apps are heavily integrated into native CocoaTouch apps and rely on my old hacked AppController.

    If there isn't any documentation or any example soon I'm going to end up just having to wing this on my own next week. Which I'd really prefer not to do.
     
  16. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    well, samples are still not up (sigh)
    here, i uploaded some for you to try out
    http://beta.unity3d.com/alexey/OverlayUI.zip
    this one is quite simple and straightforward - it customize default root view controller to show date picker (and pass data back and forth)
    http://beta.unity3d.com/alexey/NavigationController.zip
    it shows how to insert unity view into NavigationController. It uses your usual default view controller as root, but now unity view is a bit deeper 8)

    As usual, if you think that we need to have a bit more samples in this area - spill it. I am fine with doing some more quick projects.
     
    chan9118 likes this.
  17. fraques

    fraques

    Joined:
    Aug 9, 2012
    Posts:
    8
    Thanks a million times for this. I didn't realize it was possible to do it in such a clean and elegant way. Just one more thing though, how can I get it to work with storyboards? Usually, I just create my layouts in a storyboard and iOS will launch my first ViewController automatically with no real code.

    Imagine this scenario: I have an application with a few scenes. On the first, I select what I want to see next. One of the options is a scene where I have some Unity content inside a view (not fullscreen, just a portion of the window).

    $Storyboard.png

    How can I achieve this? I have been using Unity for some years now, but I have only started dealing with native iOS code a few weeks ago and this is frying my brain. Thanks for your help
     
  18. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    challenge accepted! 8)
    mind you - i have no idea what storyboard is (i wont even call mself objc programmer), but i'll a bit into this next week
     
  19. fraques

    fraques

    Joined:
    Aug 9, 2012
    Posts:
    8
    Thank you, Alexey! I understand that Objective C may not be your language of choice, but while reading your post I couldn't help but think "Alright, yeah! Artillery is coming" :)

    I will be pleased to give you a quick tour of Storyboards. (I hope this is not considered off topic)

    Storyboards is a fast way to layout your apps with little to no code. It gives you a visual editor where you can arrange your views and controls and iterate it very fast with the feedback of designers or clients.

    For example, let's build a prototype for your second project using storyboards.

    In Xcode, we create a new project and choose Application > Single View Application. On the next dialog we check the option "Use Storyboards". We will then see this

    $img01.png

    Storyboards are only available since iOS 5, so we make sure we target a recent version. The MainStoryboard will be launched when the application starts. If we take a look in the MainStoryboard.storyboard file, we'll see that it already contains an empty ViewController that we can edit. The arrow in the left means this is the first ViewController that will be displayed.

    $img02.png

    If we select this ViewController and open the Identity Inspector, we'll see that it is an instance of class ViewController (subclassed from UIViewController). This is the place where we can assign different classes to our objects.

    $img03.png

    So now let's create another ViewController for our second scene. We just need to open the Object Library and drag a new UIViewController to the storyboard. We will have this

    $img04.png

    Now we change the color of the first view to blue to differentiate it and add a button to it from de Object Library. To make this button open the second ViewController we just need to right click on it (or ctrl-click) and drag to the second scene. It will ask what kind of Action Segue we want. We can choose Push. A final step is to embed everything inside a Navigation Controller, so we select the first ViewController and do

    Editor > Embed In > Navigation Controller

    Now he have this

    $img05.png

    And it should be working now. We can run it on the simulator to test it out. It's a working prototype and we haven't write a single line of code yet. So you can see how storyboards are useful. In fact, all the applications that I have seen this last few weeks (in other words, my entire Objective C career :) ) use this workflow.

    To make the second scene display a web page, we just need a few more seconds of work. We create a new Objective C class, derived from UIViewController, name it WebViewController, for example, and define it as the class of our second ViewController in the Identity Inspector. Then we choose it's inner view and make it derive UIWebView. Then we open the Assitant Editor to show simultaneously our storyboard and WebViewController.h. We drag from the view to the @interface and we create an outlet named webView.

    A bit of code now, in the WebViewController.m we put this inside viewDidLoad

    Code (csharp):
    1.  
    2. NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://unity3d.com"]];
    3.  
    4. [self.webView loadRequest:request];
    5.  
    6.  
    And our prototype is almost done! We only need to fill that blue view in the first scene with our Unity content. Unfortunately I have no idea how that can be done. So that's where your help will be immensely useful :)

    Here's hoping it can be done
    Cheers!
     
  20. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    I got a unity view working within a storyboard. This is a very simple example, but make sure:

    1. You have a StoryBoard created and that it is set as the "Main Storyboard" in the Target Summary settings (it should also show up in the plist).

    2. Add the window property to UnityAppController.h like so:

    Code (csharp):
    1. @property (strong, nonatomic) UIWindow *window;
    2.  
    3. Your createViewHierarchyImpl function could look like this:

    Code (csharp):
    1.  
    2. - (void)createViewHierarchyImpl;
    3. {
    4.    
    5.     // STORYBOARD
    6.    
    7.     // Attempt 1: don't set the main storyboard in the target settings; just instantiate it programmatically.
    8.     // THIS DOESN'T SEEM TO WORK
    9. /*    UIStoryboard *storyBoard    = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    10.     UIViewController *mainVC    = [storyBoard instantiateInitialViewController];
    11.     _rootController             = mainVC;
    12.     _rootView                   = mainVC.view;*/
    13.    
    14.     // Attempt 2: set the main storyboard in the target settings and then grab the existing view controller
    15.     // THIS SEEMS TO WORK
    16.     _rootController             = [self.window rootViewController];
    17.     _rootView                   = _unityView;// _rootController.view;
    18. }
    19.  
     
  21. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    The problem with my above post re. storyboards is I can only get it to work if I assign the Unity view to _rootView. If I want to assign it anything other view later in the storyboard, the assignment works, but the root view on the Storyboard no longer accepts input. Any thoughts?

    For example, if lines 15 and 16 in the previous post are changed to:

    _rootController = [self.window rootViewController];
    _rootView = _rootController.view;

    ... then the root view doesn't accept touch input. I have a button on there that I cannot press. Thoughts?
     
  22. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    Ok, I got the Storyboard issue solved...

    Code (csharp):
    1.  
    2. - (void)createViewHierarchyImpl;
    3. {
    4.     UIStoryboard *storyBoard    = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    5.     UIViewController *mainVC    = [storyBoard instantiateInitialViewController];
    6.    
    7.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    8.     self.window.rootViewController = mainVC;
    9.  
    10.     _rootController             = [self.window rootViewController];
    11.     _rootView                   = _rootController.view;
    12. }
    And then just assign the UnityAppController's unityView property to some UIView somewhere in the storyboard.
     
  23. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    Sounds good...

    How do you avoid Unity overwriting the storyboards in the Xcode project when it generates the code?

    Do you just get it to Append to the project rather than replace?

    cheers

    N
     
  24. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    This is a good question. What I do is generate the Unity project, but have my own separate Xcode project. I then reference the files in Data, Classes, and Libraries, so that whenever I rebuild on the Unity side, I don't lose all of the native code (or storyboards, etc.) that I've added in my own Xcode project. In other words, I don't even use the Xcode project file generated by Unity itself, although I do refer to it to help me get the Build settings correct in my own Xcode project.

    But yes, you could append rather than replace the build output, but this is dangerous because if you ever replace by accident... well then you could potentially lose a lot of work (unless you're regularly committing to a repo).
     
    Last edited: Sep 19, 2013
  25. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    That's interesting, I was wondering whether it would work the other way around somehow i.e. get Unity to generate a project after copying the Xcode assets to its directory.

    In your example, how do you know which Unity files to reference?

    I see Classes and Libraries, but no Data.

    Have you managed to get a seamless workflow?

    N
     
  26. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    Yes, I've managed to get a seamless workflow. Takes a bit to get the native Xcode project set up, but once you're there and you've done it a few times it's not really that difficult.

    Re. Data folder. If you've done an iOS build from Unity you should definitely see a Data folder in the output; it contains the UnityEngine.dll, etc.

    I'm going to approach my employer about publishing the workflow on the Unity wiki or on our website or something. Could take awhile though.
     
    Last edited: Sep 19, 2013
  27. DavidMM

    DavidMM

    Joined:
    Sep 20, 2013
    Posts:
    2
    Hello to everyone,

    I'm having some problems when subclassing the Unity AppController and using a storyboard.

    I've been able to integrate into the XCode project generated by Unity the code from my pre-existing Xcode project which has just one storyboard. The problem I'm facing now is that the pre-existing project was designed to work just in landscape (target orientation set to work in landscape on the Summary tab and the all scenes in the storyboard set to Orientation=Landscape), but after integrating both projects the views from the storyboard rotate also into portrait mode.

    ¿Any ideas why this is happening?

    Tnx


    PS: the integration is done by

    #import <UIKit/UIKit.h>
    #import "UnityAppController.h"
    #import "UI/UnityView.h"
    #import "iPhone_View.h"

    @interface MyAppController : UnityAppController
    {

    }
    - (void)createViewHierarchyImpl;
    @end

    @implementation MyAppController
    - (void)createViewHierarchyImpl;
    {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:mad:"MainStoryboard" bundle:nil];

    UIViewController *eiaVC = [storyboard instantiateInitialViewController];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.window.rootViewController = eiaVC;

    _rootController = [self.window rootViewController];

    _rootView = _rootController.view;
    }


    @end
     
  28. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    Hi DavidMM,

    I think the issue is that the UnityAppController takes over handling the orientation. What I did to get around this was to override the application:supportedInterfaceOrientationsForWindow function. For example:

    Code (csharp):
    1.  
    2. - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    3. {
    4.         // uncomment the appropriate line based on your supported orientation
    5.  
    6. //  return (1 << UIInterfaceOrientationPortrait);
    7. //        return (1 << UIInterfaceOrientationPortraitUpsideDown);
    8. //        return (1 << UIInterfaceOrientationLandscapeRight);
    9.         return (1 << UIInterfaceOrientationLandscapeLeft);
    10.  
    11.         // or, if supporting multiple orientations, then follow this pattern:
    12.  
    13.         //return   (1 << UIInterfaceOrientationPortrait) | (1 << UIInterfaceOrientationPortraitUpsideDown)
    14.         //     | (1 << UIInterfaceOrientationLandscapeRight) | (1 << UIInterfaceOrientationLandscapeLeft);
    15. }
    16.  
    17.  
    18.  
    HTH.
     
  29. trickpirata

    trickpirata

    Joined:
    Jun 17, 2011
    Posts:
    12
    Yo Jacksmash2012,

    I've managed to get the storyboard working but having problems reassigning unity's view. Do I need to do this programatically? I am trying to just set UnityView to the storyboard using this method but it seems like it is not working. $9WYWtXg.png

    I am always getting this error
    Code (csharp):
    1. *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UnityView's implementation of -layoutSubviews needs to call super.'
    2. *** First throw call stack:
    3. (0x325c23e7 0x3a2bd963 0x325c229d 0x32e98fa3 0x343d4977 0x34180513 0x341800b5 0x34180fd9 0x341809c3 0x341807d5 0x34180639 0x32597941 0x32595c39 0x32595f93 0x3250923d 0x325090c9 0x360e833b 0x344252b9 0x2b440 0x3a6eab20)
    4. libc++abi.dylib: terminate called throwing an exception
    Any tips? Thanks!

    ---------------------------UPDATE!
    I have managed to remove the error by editing the UnityView.mm script adding
    Code (csharp):
    1.  [super layoutSubviews];
    at the end of - (void)layoutSubviews class but still unity view is not loading. Any help will be much appreciated! :)
     
    Last edited: Sep 23, 2013
  30. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    omhm, yeah, that looks like our bad
    check UI/UnityView.mm and add [super layoutSubviews] to out layoutSubviews impl.
     
  31. trickpirata

    trickpirata

    Joined:
    Jun 17, 2011
    Posts:
    12
    Yep. But the Unity is still not loading on my UIView. It is just showing a black interface. I wonder why. :/

    ----UPDATE

    Seems like unity is loading in background but it seems like XCode's view is in top of Unity. Any other tips?
     
    Last edited: Sep 23, 2013
  32. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    corrtrickpirata,

    You can't assign the UnityView in the storyboard (EDIT: this isn't true. See my next posts). You'll need to do it programmatically. Just create a custom UIViewController class, and in the viewDidLoad function assign the unity view to the view controller's root view via: self.view = unityView

    You'll need to grab the unityView property from the UnityAppController (which you can access just like you would access any UIAppDelegate).
     
    Last edited: Sep 23, 2013
  33. trickpirata

    trickpirata

    Joined:
    Jun 17, 2011
    Posts:
    12
    I am kinda newbie to Obj-C here. But it seems like my unity controller is still blank. Sorry for much spoonfeeding but I really need some help here. Lol. Here's my ViewController.h
    Code (csharp):
    1.  
    2. #import <UIKit/UIKit.h>
    3. #import "AppDelegate.h"
    4. #import "UnityAppController.h"
    5.  
    6. @interface ViewController : UIViewController
    7. {
    8.  
    9. }
    10. @property(strong, nonatomic) UnityAppController *unityController;
    11.  
    12. @end
    13.  
    and here's my ViewController.mm
    Code (csharp):
    1.  
    2. #import "ViewController.h"
    3.  
    4. @implementation ViewController
    5.  
    6. - (void)viewDidLoad
    7. {
    8.     [super viewDidLoad];
    9.     // Do any additional setup after loading the view, typically from a nib.
    10.     //TODO: Assign unity view to this ViewController
    11.    
    12.     self.view = _unityController.unityView;
    13. }
    14.  
    15. - (void)didReceiveMemoryWarning
    16. {
    17.     [super didReceiveMemoryWarning];
    18.     // Dispose of any resources that can be recreated.
    19. }
    20.  
    21. @end
    22.  
    I already set the view controllers on my storyboard and I can confirm that viewDidLoad is loading. My app outputs a blank screen. Any help?

    Thanks!
     
  34. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    Ok, well since you're new :)

    Code (csharp):
    1.  
    2. #import "ViewController.h"
    3. #import "UnityAppController.h"
    4.  
    5. @implementation ViewController
    6.  
    7. - (void)viewDidLoad
    8. {
    9.     [super viewDidLoad];
    10.  
    11.     // Do any additional setup after loading the view, typically from a nib.
    12.  
    13.     UnityAppController *appController = (UnityAppController*) [[UIApplication sharedApplication] delegate;
    14.     self.view = appController.unityView;
    15. }
    16.  
    17. ...
    18.  
    19.  
     
  35. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    Anyhow,

    I totally lied in a previous post. You CAN assign UnityView in the storyboard layout just like you did. The reason you got the error is because of what Alexey said above, ie., they missed a super call in UnityView.mm.

    So, find UnityView.mm, and then find the layoutSubviews function, and make sure this is the first call in that function:

    [super layoutSubviews];

    Then, you should be able to assign UnityView in the storyboard layout just like you did (assuming you had selected a UIView object).
     
  36. GuyTidhar

    GuyTidhar

    Joined:
    Jun 24, 2009
    Posts:
    320
    I used to subclass UIApplication's 'sendEvent' method in order to detect status bar touches which unity does not detect.
    Now in iOS this does not work since when ever I set the UIApplication argument with our subclass, not events get fired at all to unity.

    So I'm wondering how can I detect these touches now that we're using Unity 4.2.1 and iOS 7.

    Thanks!
     
  37. trickpirata

    trickpirata

    Joined:
    Jun 17, 2011
    Posts:
    12
    At last! I got it. I just programmatically added Unity's UI View as a subview for my View Controller and because unityView is always appearing in front of my storyboard, I had to use
    Code (csharp):
    1.  
    2. [self.view sendSubviewToBack:appController.unityView];
    3.  
    so my navigation bar is infront of the unity view. Thanks for the help, jacksmash2012!

    Here's the whole code for my ViewController.mm by the way.

    Code (csharp):
    1.  
    2. #import "ViewController.h"
    3.  
    4. @implementation ViewController
    5.  
    6. - (void)viewDidLoad
    7. {
    8.     [super viewDidLoad];
    9.     // Do any additional setup after loading the view, typically from a nib.    
    10.     UnityAppController *unityController = (UnityAppController*) [[UIApplication sharedApplication]
    11.                                                                delegate];
    12.     //self.view = appController.unityView;
    13.     [self.view addSubview:unityController.unityView];
    14.     [self.view sendSubviewToBack:unityController.unityView];
    15.     [unityController unityPause:NO];
    16. }
    17.  
    18. - (void)didReceiveMemoryWarning
    19. {
    20.     [super didReceiveMemoryWarning];
    21.     // Dispose of any resources that can be recreated.
    22. }
    23.  
    24. @end
    25.  
    26.  
     
  38. GuyTidhar

    GuyTidhar

    Joined:
    Jun 24, 2009
    Posts:
    320
    Ok, so I managed to get our UIApplication subclass to work by giving it to the UIApplicationMain method followed by setting UnityAppController as it's delegate.
    That makes unity function as usual, but I the overriding sendEvent method I did, does not get fired. Can I still have it fired so we can detect status bar touches? Might be the touchesBegan methods and sorts hindering with what I did?

    Edit, here is what I did:
    Code (csharp):
    1.  
    2.     UIApplicationMain(argc, argv, @"MyUIApplicationSubclass", nil);
    3.     UnityAppController *unityAppController = [[UnityAppController alloc] init];
    4.     [UIApplication sharedApplication].delegate = unityAppController;
    5.  
     
    Last edited: Sep 24, 2013
  39. algizmo

    algizmo

    Joined:
    Oct 5, 2013
    Posts:
    4
    Hello good people,
    I am trying to integrate a storyboard and I am totally stuck..
    I followed jacksmash2012 posts but cannot get it to work fully...
    Here is what I did:
    added the following line to UnityAppController.h:

    Code (csharp):
    1. @property (strong, nonatomic) UIWindow *window;
    then added the following (to createViewHierarchyImpl):

    Code (csharp):
    1.  
    2. UIStoryboard *storyBoard    = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];
    3. UIViewController *mainVC    = [storyBoard instantiateInitialViewController];
    4. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    5. self.window.rootViewController = mainVC;
    6. _rootController             = [self.window rootViewController];
    7. _rootView                   = _rootController.view;
    I have a button on initial view controller which gives an alert message.

    If I run it, it loads but the button is not clickable..
    Any ideas what could cause this?

    Thank you in advance for your help!
     
  40. jacksmash2012

    jacksmash2012

    Joined:
    Sep 21, 2010
    Posts:
    27
    If you look at the code in createViewHierarchyImpl, you've now created your own initial view controller. I can't see how you have your storyboard set up, but how does the view controller you've just created know about the button on your storyboard? It doesn't, and so it can't control it.

    I'd suggested just assigning UnityView to the root view of your initial view controller on the storyboard. This was discussed further up this thread.
     
  41. algizmo

    algizmo

    Joined:
    Oct 5, 2013
    Posts:
    4
    I am not sure what you mean by that. I am getting a storyboar and using its initial view controller and the button is part of that controller. So, why then the view controller does not know about a button on that view controller?..

    Maybe I was not clear enough, but I was not shooting for unity view on my initial view controller's view.. I was trying to make something like fraques wanted.

    Anyhow, I got it to work the way I wanted. Not sure if that's the right way to do it (since I am quite new to xcode and obj-c).


    I used unity 4.2.1 and xcode 5.

    1. Built a simple scene in Unity for iOS (used standard settings)
    2. In xcode project, created custom application controller and extended from UnityAppContrller.mm :

    AppController.m
    Code (csharp):
    1.  
    2. @implementation AppController
    3.  
    4. - (void)createViewHierarchyImpl;
    5. {
    6.     UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle: nil];
    7.     UIViewController *mainVC    = [mainStoryboard instantiateInitialViewController];
    8.    
    9.     _rootController    = [[UnityDefaultViewController alloc] init];
    10.     _rootView     = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    11.     [_rootView addSubview : mainVC.view];
    12. }
    13. @end
    14.  
    15. IMPL_APP_CONTROLLER_SUBCLASS(AppController)
    16.  
    3. Added the window property to UnityAppController.h like so:

    Code (csharp):
    1. @property (strong, nonatomic) UIWindow *window;
    4. Created a storyboard with 2 view controllers and navigation controller. One view controller for the menu and another one for the game. Set the menu view controller as a starting point in the storyboard. Set the storyboard as Main Storyboard:

    $story.png

    5. Added the following lines to viewDidLoad method of GameViewController.m (this loads unityView to the main view of the game view controller):

    Code (csharp):
    1.  
    2. UnityAppController *appController = (UnityAppController*) [[UIApplication sharedApplication] delegate];
    3. self.view = (UIView*)appController.unityView;
    4.  
     
    Last edited: Oct 14, 2013
  42. peiyinchao

    peiyinchao

    Joined:
    Oct 22, 2013
    Posts:
    1
    Hi Trickpirata,

    I have been struggling around with adding a Storyboard and a custom ViewController class to the standard xCode project exported from Unity.
    I would like to simply add the UnityView in a custom UIView/UnityView that I placed on my Storyboard.

    From your post you seem to have managed, which is really impressive. Would you please be so kind to share your xCode project with me as an example?

    Many thanks in advance.

    Best,
    Pei-Yin Chao
     
  43. jpatinop80

    jpatinop80

    Joined:
    Jul 29, 2012
    Posts:
    55
    Hello all
    I have a game on unity and I want to use OverlayUI files from Alexy, but the xcode app is quite complicate because is a radio web player, and I get it in Storyboard, so I want to overlay the radio web in to the game, with the basic control, play/pause and volume control...
    is that possible?
    thanks
     
  44. jpatinop80

    jpatinop80

    Joined:
    Jul 29, 2012
    Posts:
    55
    Is there the possibility to overlay a hole window not just an element? I would like to overlay a music player or radio web player, is that possible?
     
  45. jpatinop80

    jpatinop80

    Joined:
    Jul 29, 2012
    Posts:
    55
    hi, I can't find GameViewController.m, I'm lost!!!!
     
  46. trickpirata

    trickpirata

    Joined:
    Jun 17, 2011
    Posts:
    12

    Hello Pei-Yin Chao,

    Sorry for the super late reply. Here's my AppDelegate.mm


    Code (csharp):
    1.  
    2.  
    3. #import "AppDelegate.h"
    4.  
    5. @implementation AppDelegate
    6.  
    7. @synthesize unityController = _unityController;
    8.  
    9. - (void) createViewHierarchyImpl
    10. {
    11.     if(_unityController == nil)
    12.     {
    13.         _unityController = [[UnityAppController alloc] init];
    14.         NSLog(@"Unity Controller set");
    15.     }
    16.    
    17.     UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    18.    
    19.     UIViewController *mainVC = [storyBoard instantiateInitialViewController];
    20.    
    21.     self._window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    22.    
    23.     self._window.rootViewController = mainVC;
    24.     self._window.clipsToBounds = NO;
    25.    
    26.     _rootController = [self._window rootViewController];
    27.    
    28.     _rootView   = _rootController.view;
    29.     [self._window makeKeyAndVisible];
    30.     [self pauseUnity];
    31. }
    32.  
    33. - (void) playUnity
    34. {
    35.     [_unityController unityPause:NO];
    36. }
    37.  
    38. - (void) pauseUnity
    39. {
    40.     [_unityController unityPause:YES];
    41. }
    42. @end
    43.  
    44. IMPL_APP_CONTROLLER_SUBCLASS(AppDelegate)
    And here's my ViewController attached to a UIView inside a storyboard.

    Code (csharp):
    1.  
    2. #import "StyleViewController.h"
    3.  
    4. @implementation StyleViewController
    5. - (void)viewDidLoad
    6. {
    7.     [super viewDidLoad];
    8.  
    9.     // Do any additional setup after loading the view, typically from a nib.    
    10.     UnityAppController *unityController = (UnityAppController*) [[UIApplication sharedApplication]
    11.                                                                delegate];
    12.     //self.view = appController.unityView;
    13.     [self.view addSubview:unityController.unityView];
    14.     [self.view sendSubviewToBack:unityController.unityView];
    15.     [unityController unityPause:NO];
    16.    
    17.    
    18. }
    19.  
    20. - (void) viewDidUnload
    21. {
    22.     NSLog(@"Exit");
    23. }
    24.  
    25. - (void)didReceiveMemoryWarning
    26. {
    27.     [super didReceiveMemoryWarning];
    28.     // Dispose of any resources that can be recreated.
    29. }
    30.  
    31. @end
    32.  
    Let me know if you got it working. To attach UnityView in a UIView, you just need this code(as you can see in my view controller)

    Code (csharp):
    1.    
    2.     UnityAppController *unityController = (UnityAppController*) [[UIApplication sharedApplication]
    3.                                                                delegate];
    4.     //self.view = appController.unityView;
    5.     [self.view addSubview:unityController.unityView];
    6.     [self.view sendSubviewToBack:unityController.unityView];
    Just be sure to #import UnityAppController in order to access the unity controller.
     
    Last edited: Oct 29, 2013
  47. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    Hi all, I'm also trying to load a Unity from my storyboard on a button click.
    So tried to do similar to trickpirata's code.
    Do I need to call [super application:application didFinishLaunchingWithOptions:launchOptions]; from the didFinishLaunchingWithOptions of my AppDelegate.mm?
    When I add that, the Unity part start running at start. But I need it to start only when the button is clicked. If I comment the above line, then even when I click the button unity doesn't get called.

    Please let me know what I'm doing wrong and what is missing in my code. Thanks

    This is my code

    //AppDelegate.h
    Code (csharp):
    1. #import <UIKit/UIKit.h>
    2. #import "UnityAppController.h"
    3. @interface AppDelegate : UnityAppController
    4.  
    5. @property (strong, nonatomic) UIWindow *window;
    6. @property (strong, nonatomic) UnityAppController *unityController; // unity
    7. @end
    ///AppDelegate.mm

    Code (csharp):
    1. #import "AppDelegate.h"
    2.  
    3. @implementation AppDelegate
    4. @synthesize window = _window;
    5. @synthesize unityController = _unityController;
    6.  
    7. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    8. {
    9.     //[super application:application didFinishLaunchingWithOptions:launchOptions];
    10.     // Override point for customization after application launch.
    11.     return YES;
    12. }
    13.  
    14. - (void)createViewHierarchyImpl;
    15. {    
    16.     UIStoryboard *storyBoard    = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    17.    
    18.     UIViewController *mainVC = [storyBoard instantiateInitialViewController];
    19.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    20.     self.window.rootViewController = mainVC;
    21.     self.window.clipsToBounds = NO;
    22.     _rootController = [self.window rootViewController];
    23.     _rootView   = _rootController.view;
    24.     [self.window makeKeyAndVisible];
    25.     [self pauseUnity];
    26.    
    27. }
    28.                
    29.  
    30. - (void) playUnity
    31. {    
    32.     [_unityController unityPause:NO];    
    33. }
    34.  
    35. - (void) pauseUnity
    36. {
    37.     [_unityController unityPause:YES];    
    38. }
    39.  
    40. @end
    41. IMPL_APP_CONTROLLER_SUBCLASS(AppDelegate);
    42.  
    //ViewController.h
    Code (csharp):
    1. #import <UIKit/UIKit.h>
    2. #import "UnityAppController.h"
    3. @interface ViewController : UIViewController
    4. - (IBAction)btnClick:(id)sender;
    5. //@property (strong, nonatomic) IBOutlet UIView *myview;
    6.  
    7. @end
    //ViewController.m
    Code (csharp):
    1. #import "ViewController.h"
    2.  
    3. @interface ViewController ()
    4.  
    5. @end
    6.  
    7. @implementation ViewController
    8. @synthesize myview;
    9. - (void)viewDidLoad
    10. {
    11.     [super viewDidLoad];  
    12. }
    13.  
    14. - (void)didReceiveMemoryWarning
    15. {
    16.     [super didReceiveMemoryWarning];
    17.     // Dispose of any resources that can be recreated.
    18. }
    19.  
    20. - (IBAction)btnClick:(id)sender {
    21.     NSLog(@"Play click");
    22.     // Do any additional setup after loading the view, typically from a nib.
    23.    
    24.     UnityAppController *unityController = (UnityAppController*) [[UIApplication sharedApplication]
    25.                                                                  
    26.                                                                  delegate];
    27.      //self.view = appController.unityView;
    28.    
    29.     [self.view addSubview:unityController.unityView];
    30.    
    31.     [self.view sendSubviewToBack:unityController.unityView];
    32.    
    33.     [unityController unityPause:NO];
    34.  
    35. }
    36. @end
    37.  
    And added this method to the UnityAppController.mm
    Code (csharp):
    1. - (void)unityPause:(BOOL)pause
    2. {
    3.     UnityPause(pause);
    4. }
    and
    Code (csharp):
    1. - (void)unityPause:(BOOL)pause;
    to UnityAppController.h



    @Trickpirata - if possible please share your code files with us. It'll be really helpful. Have been struggling with this whole day. Thanks
     
    Last edited: Nov 9, 2013
  48. Millerntor

    Millerntor

    Joined:
    Dec 20, 2013
    Posts:
    1
    Could you please show me the steps?
    I have tried for quite some time now, but can't make it work.
     
  49. ty_123

    ty_123

    Joined:
    Jan 6, 2014
    Posts:
    2
    I have the same issue right now, did you find out?





     
  50. Parris-Person

    Parris-Person

    Joined:
    Dec 19, 2013
    Posts:
    2
    Hi everybody, i read this thread trying to follow the steps of jacksmash2012 to get work a unity project with a storyboard with no success.
    First of all i generated the project in Xcode, created the storyboard, set the main interface to the storyboard,
    add
    Code (csharp):
    1. @property (strong,nonatomic) UIWindow *window
    to the UnityAppController.h file; ,
    in UnityAppController.mm i changed the function -(void)createViewHierarchyImpl to
    Code (csharp):
    1. - (void)createViewHierarchyImpl;
    2.  
    3. {
    4.  
    5.     UIStoryboard *storyBoard    = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    6.  
    7.     UIViewController *mainVC    = [storyBoard instantiateInitialViewController];
    8.  
    9.    
    10.  
    11.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    12.  
    13.     self.window.rootViewController = mainVC;
    14.  
    15.  
    16.  
    17.     _rootController             = [self.window rootViewController];
    18.  
    19.     _rootView                   = _rootController.view;
    20.  
    21. }

    and finally in storyboard i put a view controller and change is uiview class to unity view
    when i try this in the device only show a white screen.Can anyone tell me whats the problem or explain me more specific how storyboard can be configured to work.
    Thanks