Search Unity

  1. The 2022.1 beta is now available for testing. To find out what's new, have a look at our 2022.1 beta blog post.
    Dismiss Notice

Unity AppController subclassing.

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

  1. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    @Parris Person - Have a look at the code I posted, 3 posts before. It seems to work for me.
    One thing missing there is you need to call [super application:application didFinishLaunchingWithOptions:launchOptions]; from the didFinishLaunchingWithOptions of AppDelegate.mm
    Hope this helps.
     
  2. ty_123

    ty_123

    Joined:
    Jan 6, 2014
    Posts:
    2
    Anyone has memory issue if doing this way? my project taks 400+ mb memory, which is really bad user expreience.

    This is happen after call unityPause and unityPlay, is there any way to optimize?

    Thanks!
     
  3. dttngan91

    dttngan91

    Joined:
    Nov 21, 2013
    Posts:
    80
    Yes, I have the same issue on memory stuff of unity integration in xCode. I really want to completely remove unity from xCode project after using that instead of Unity(pause). How can I do that? is it possible?
     
  4. developer.1

    developer.1

    Joined:
    Mar 17, 2013
    Posts:
    1
    Here is my error
    "Warning: Attempt to present <GKLeaderboardViewController: 0x1f5c2650> on <ViewController: 0x1dd8d7a0> whose view is not in the window hierarchy!"


     
  5. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,116
    Thought I'd come back here to point this out and suggest a change, and developer.1 this is actually the solution to your problem.

    So here is my custom hierarchy implementation function

    Code (csharp):
    1.  
    2. - (void)createViewHierarchyImpl;
    3. {
    4.     UIStoryboard *storyBoard    = [UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil];
    5.     UIViewController *mainVC = [storyBoard instantiateInitialViewController];
    6.     UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    7.     window.rootViewController = mainVC;
    8.    
    9.     _rootController = [window rootViewController];
    10.     _rootView   = _rootController.view;
    11.  
    12.     UnityPause(true);
    13.    
    14.     [[UnityManager sharedManager] initializeUnity];
    15. }
    16.  
    I am making my own rootViewController and my own view, assigning them to _rootController and _rootView. The unityAppController then presents these first.

    The problem however with this is that when I switch to the unity view, I am swapping rootViewControllers. I have my native app UI on one viewController, than a UnityViewController separate from that and I switch the two back and forth on a single UIWindow.

    BUT when I call setRootViewController on the UIWindow and change it to the unity window. The initial _rootController and _rootView variable remain the same original non-unity viewController I supplied to them in the createViewHierarchyImpl function. This causes a problem because it breaks any code like Handheld.ShowFullScreenMovie, or any of the Etcetera plugin functions which present a modal view controller. It breaks these things because they rely on the function UnityGetGLViewController() to figure out which view controller to attach the modal view to. Which UnityGetGLViewController() returns whatever is set to the _rootController variable.

    I have a temporary workaround to this issue by creating this function in my app delegate:

    Code (csharp):
    1.  
    2. - (void)setUnityRootController
    3. {
    4.     _rootController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
    5.     _rootView = [[[[UIApplication sharedApplication] keyWindow] rootViewController] view];
    6. }
    7.  
    Anytime I switch the rootViewController on the UIWindow from the UnityViewController to another one, I call that function to update those variables. But I think this is just a hack. It would be much smarter if the _rootController _rootView variables or the UnityGetGLViewController() worked in a different way to not need that hack function.
     
    Last edited: Mar 5, 2014
  6. Batigol

    Batigol

    Joined:
    Oct 17, 2012
    Posts:
    233
    hi all,

    I tried to integrate Unity with native code using instruction in this thread but cannot :(
    Search around on internet and compile with this thread, I found a way to do it
    But it cannot load unity view at beginning, always crash if I put in viewdidload or nothing happen when I put into nitWithNibName
    I just work if I put the unityview inside onClick button

    Does anyone have ideas to make it show UnityView at begining?
    Nothing happen at begining
    $AtFirstTime.png
    Show UnityView after click Test button
    $AfterClickTest.png ?
    AppDelegate.m
    Code (csharp):
    1. #import "AppDelegate.h"#import "MainView.h"
    2. @implementation AppDelegate
    3. @synthesize window;
    4. -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    5. {
    6.     [super application:application didFinishLaunchingWithOptions:launchOptions];
    7.     self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    8.     MainView *mainView = [[MainView alloc] init];
    9.    
    10.     UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:mainView];
    11.     self.window.rootViewController = nav;
    12.     [self.window makeKeyAndVisible];
    13.     return YES;
    14. }
    15.  
    16.  
    17. @end
    MainView.m
    Code (csharp):
    1. #import "MainView.h"#import "MySingleton.h"
    2. #import "SecondView.h"
    3. #import "UnityAppController.h"
    4. @interface MainView ()
    5. @end
    6.  
    7.  
    8. @implementation MainView
    9. @synthesize unityView;
    10. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    11. {
    12.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    13.     if (self) {
    14.         // Custom initialization
    15.         NSLog(@"init zzzzz");
    16.         UnityAppController *app = [(UnityAppController*)[UIApplication sharedApplication] delegate];
    17.         [self.unityView addSubview:app.unityView];
    18.  
    19.  
    20.     }
    21.     return self;
    22. }
    23.  
    24.  
    25. - (void)viewDidLoad
    26. {
    27.     [super viewDidLoad];
    28.  
    29.  
    30. }
    31.  
    32.  
    33. - (void)didReceiveMemoryWarning
    34. {
    35.     [super didReceiveMemoryWarning];
    36.     // Dispose of any resources that can be recreated.
    37. }
    38. -(void)onClick
    39. {
    40.     UnityAppController *app = [(UnityAppController*)[UIApplication sharedApplication] delegate];
    41.     [self.unityView addSubview:app.unityView];
    42. }
    43. -(void)onClick1
    44. {
    45.         SecondView *v = [[SecondView alloc] init];
    46.     [self.navigationController pushViewController:v animated:YES];
    47.    
    48.    }
    49.  
    50.  
    51. @end
     
  7. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,116
    Alexey ( or someone really knowledgable )

    I have an issue with one app I put Unity into, and its really weird. My app will stutter like once every 5 - 10 seconds. Just pause and skip a few frames.

    When I just build my Unity app via the Xcode project that Unity generated, it does not do this. It only does this when I build the project through the Xcode project that got generated when I created a new app project with Xcode.

    I have gone through my Xcode generated project, comparing everything in the build settings line by line to the Unity generate Xcode project. I cannot find any more differences between them. I assumed it was some setting in the build settings that caused this, but it seems to not be so.

    Then I thought maybe it's because I have ObjC exceptions and are ARC enabled in my Xcode generated project. But I went and enabled those in the Unity generated Xcode project, then put -fno-objc-arc on all the sources, and built it, and it does not have this issue.

    Is there something else going on here that you could help me with or point me in the direction of? I am really at a loss to think of why this is.
     
  8. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,116
    You shouldn't be making a window and doing makeKeyAndVisible, or even really setting up views in ApplicationDidLoad

    You subclass UnityAppController with your own AppDelegate.

    Then implement the function
    - (void)createViewHierarchyImpl;

    Then whatever you set these variables too:
    _rootController
    _rootView

    Is what will appear first. You don't ever need to allocate a window or makeKeyAndVisible on it.

    Then don't forget the IMPL_APP_CONTROLLER_SUBCLASS(AppController)

    This is all shown in Alexey's example... just follow them.
     
  9. Batigol

    Batigol

    Joined:
    Oct 17, 2012
    Posts:
    233
    I followed other tutorial
    http://floored.com/blog/2013/integrating-unity3d-within-ios-native-application.html
    http://alexanderwong.me/post/29949258838/building-a-ios-unity-uiview-uiviewcontroller

    Now could find the way to load it at beginning with small cheat

    Code (csharp):
    1. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    2. {
    3.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    4.     if (self) {
    5.         // Custom initialization
    6.         timer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(showUnityView) userInfo:nil repeats:NO];
    7.     }
    8.     return self;
    9. }
    10. - (void)showUnityView
    11. {
    12.     return;
    13.     [timer invalidate];
    14.     UnityAppController *app = [(UnityAppController*)[UIApplication sharedApplication] delegate];
    15.     [self.unityView addSubview:app.unityView];
    16. }
    Anyway, Alexey example is pretty simple :)
    Will use that way soon!

    By the way, could we add 2 unity game (different project) into iOS native code?
    For example, I have to small game, then I want to integrate into xcode, make 2 button
    Click each button to show each game
    Is it possible?
     
    Last edited: Apr 4, 2014
  10. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,116
    Batigal,
    Alexey is the one actually developing this at Unity. I would presume his way is the way you would want to follow, as thats the way Unity will more officially support in the future. Or am I wrong there Alexey? Are you leading us on a wild side-expiriment here?
    And, no you could not put two separate Unity project into one .ipa through Xcode. However you can combine two projects together in one Unity project and do it that way.


    Also, I have figured out the issue I was having with my Unity Cocoatouch hybrid app freezing for a millisecond every 5 seconds. The compiler needs to be C99, I had it on GNU99.

    Which brings up another point, that it'd be really nice if Unity maintained some script, or something, that with each new Unity release, you could execute it on an Xcode Project to configure it to the proper settings that Unity needs. Having to go through a manually back and forth the build settings every unity patch is tedious.
     
  11. jack_loverde

    jack_loverde

    Joined:
    Apr 16, 2014
    Posts:
    6
    I followed all the examples, it was pretty simple using subclass.
    But the problem is that this error appears:
    "Could not find the UIView class with CAEAGLLayer layer responds to selector renderFrameQCAR que" which is part of Vuforia.
    And they point to the Unity as wrong.
    Ie, that are coming and going.
    Even so, opens the camera, but does not follow the standard size, rotation is a mess ...
    Anyone know how to fix this?
     
  12. Josef Grunig

    Josef Grunig

    Joined:
    Nov 26, 2012
    Posts:
    8
    Hi Alexey,

    thank you for your precious example, it simplified lot our work integrating Unity with Native iOS Apps.
    Unfortunately there are stills some unclear points I would like to discuss with you:

    1) First of all, can we resize the UnityView at runtime? Its clear how to initialize with a fixed frame overloading initUnityView, but changing the frame at runtime distorts (stretches) the rendered image. Any help is appreciated

    2) How can we "add" instead of substituting the view property of a ViewController? The example does:
    Code (csharp):
    1.  
    2. _embedController1.view = _unityView;
    3.  
    while I would like to
    Code (csharp):
    1.  
    2. [_embedController1.view addSubView: _unityView];
    3.  
    If I do this directly on the example, I get a black scene (I see the background and object silhouette, but seems like lights are turned off).
    This is important as we would like to insert the view into existing layouts

    3) What about AutoLayouts? Adding the UnityView in a view hierarchy where sizes are computed by constraints might bring to the problem I notices at point 2. Any hint?

    Thank you very much,

    Josef Grunig





     
  13. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,466
    can you please create 2 bug reports (separate) with small repro projects? I have some ideas but i'd rather try first and then tell you the correct answer 8) (and implement in trampoline sure)
    you can drop case numbers here
     
  14. Josef Grunig

    Josef Grunig

    Joined:
    Nov 26, 2012
    Posts:
    8
    Sure,

    I reported a bug for point (1) with Case number: 604059

    Your example seems to work for point (2), a part the distortion issue and I'm not able to reproduce the light turning off. I'll take my original project (on which the issue still persists) and try to break it down to a more simple example. I'll let you know, but not before next monday.

    Bests,

    Josef Grunig
     
  15. juanfry

    juanfry

    Joined:
    Oct 29, 2013
    Posts:
    5
    Hi everyone,

    There is a different answers, different code... and it's too mess for novice programmers...
    Please, anybody could be a summarize of last post, a only answer with all steps you need to integrate unity Appcontroller as subclassing?.

    Thank you so much!
     
  16. Josef Grunig

    Josef Grunig

    Joined:
    Nov 26, 2012
    Posts:
    8
    Hi Alexey,

    here is the second bug report (case number:605239). The scene looses light information (light mapped) and the render viewport is deformed. The UnityView is added using Constraints (Autolayouts). This will be quite a common issue because auto layouts are a quite a MUST from iOS 6.0 and above and I don't know other ways this should be done. I think that the project I provided with the bug report might be a good base example for Unity and Native UI integration.

    Please let us know as soon as possible,

    Josef Grunig
     
  17. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,116
    You know if you can't follow alexey's example to get it to work you probably shouldn't, or you should probably pay someone more comfortable with it. I could write out a step by step guide to at least get it compiling in a base empty app. But thats really the easier part, the harder part is actually grabbing the right info from the already existing app and making it work in a way that doesn't break the already existing app, or your unity app. And for this there isn't a tutorial because someone has to know how the already existing app functions. This isn't something you can do without at least a moderate comfort in Xcode and ObjC... But if you make a stab at it and run into any specific issues feel free to ask.
     
    Last edited: Apr 29, 2014
  18. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,466
    i've finally got some time to look into mentioned issues (and yes, YAY at good repro projects when it is immediately apparent wassup, but even that good projects cant help with time thingy ;-))
    So, about
    In the project supplied there was a code

    Code (csharp):
    1. _embedController1 = [[UIViewController alloc] init];
    2. [_embedController1.view addSubview: _unityView];
    3.  
    4. // use full width, half height <- custom thing
    5. CGRect rect = [[UIScreen mainScreen] bounds];
    6. rect.size.height = rect.size.height / 2;
    7. _unityView.frame = rect;
    so what happens here (first part - this will get a bit uglier later ;-)):
    evenutally ios will call UnityView layoutSubviews (because you changed frame), and we will mark view as "recreate please"
    but unity wasnt informed about resolution change, so in recreateGLESSurface, when we call
    Code (csharp):
    1. UnityGetRenderingResolution(&requestedW, &requestedH);
    it will get "old" resolution (which is kinda fullscreen)
    **tiny note: it will actually be the the size of the view at the moment of unity init, so you could workaround it, but bear with me
    than there is another problem - i runned in portrait, and your changes to size made view actually landscape, and same pattern goes here: when we grab view extents we kinda still tweak it according to orientation. Meaning if you have portrait the "biggest" extent will go into height.
    So that was extra scew on top.
    Now, for a solution (which should be apparent now, right? ;-))
    i just did that in UnityView layoutSubviews
    Code (csharp):
    1. - (void)layoutSubviews
    2. {
    3.     if (_surfaceSize.width != self.bounds.size.width || _surfaceSize.height != self.bounds.size.height)
    4.     {
    5.         _surfaceSize  = self.bounds.size;
    6.         _recreateView = YES;
    7.     }
    8.  
    9.     // ADDED PART
    10.     extern bool _glesContextCreated;
    11.     if(_glesContextCreated)
    12.     {
    13.         UnityRequestRenderingResolution(_surfaceSize.width * self.contentScaleFactor, _surfaceSize.height * self.contentScaleFactor);
    14.         if(_surfaceSize.width > _surfaceSize.height)
    15.             UnitySetScreenOrientation(landscapeLeft);
    16.     }
    17.     <...>
    18.  
    Sure, just setting landscapeLeft might be not totally good, but i hope you've got the idea.


    P.S. Sure, i'm not saying "you have workaround, nothing to do, YAY" - it will be fixed, but you can try that for a while
    EDIT: yep, constraints issue is very same and solved in exactly same way
     
    Last edited: May 22, 2014
  19. Josef Grunig

    Josef Grunig

    Joined:
    Nov 26, 2012
    Posts:
    8
    It works like a charm, thank you for your precious suggestion.
    Josef Grunig
     
  20. hosepha

    hosepha

    Joined:
    Nov 22, 2012
    Posts:
    22
    Hi All!

    Great advice on this thread by people much cleverer than me but somehow i'm still getting mixed up! The good news is, I can get my Unity view into my storyboard and see it and interact with it which is great. Thing is i'm not sure i'm doing it right since some of the commands I'm expecting to work, given what has been written above, don't do what i'm expecting.

    Specifically I don't seem to be able to follow the exact example from Jack Smash in createViewHierarchyImpl. It runs, displays as I expect, but leaves me unable to interact with the buttons on the view. My storyboard contains two views in a navigation controller. The first view simply contains a button to segue to the next view. That should contain unity and some buttons to interact with it.

    I copied this code and placed it in my subclass of UnityAppController:

    Code (csharp):
    1. - (void)createViewHierarchyImpl;
    2. {
    3.     UIStoryboard *storyBoard    = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    4.     UIViewController *mainVC    = [storyBoard instantiateInitialViewController];
    5.  
    6.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    7.     self.window.rootViewController = mainVC;
    8.  
    9.     _rootController             = [self.window rootViewController];
    10.     _rootView                   = _rootController.view;
    11. }
    A later example in this thread suggests the following line replace the _rootController assignment :

    Code (csharp):
    1. _rootController    = [[UnityDefaultViewController alloc] init];
    This works and allows me to interact with the buttons but it feels wrong! Is it?

    Then onto the view assignments...

    The only way I've been able to display my Unity scene is with a custom ViewController. This is despite following the suggested change to iPhone_view, which part of the thread suggests should allow me to assign the UnityScene in the Interface builder. Am I reading this wrong? Is a custom viewController required?

    Going with what works, I create a custom viewController script and assign it to my second 'scene' in the Interface Builder. Then implement the viewDidLoad method as:

    Code (csharp):
    1. - (void)viewDidLoad
    2. {
    3.     [super viewDidLoad];
    4.     UnityAppController *appController = (UnityAppController*) [[UIApplication sharedApplication] delegate];
    5.     self.view = (UIView*)appController.unityView;
    6. }
    7.  
    Works fine, except it blows away the buttons I had in the view to start with. I guess that makes sense, i'm getting rid of my old view and replacing it with with Unity's one (Probably causing a nice little memory leak in the process?!).

    So I tried:

    Code (csharp):
    1.  
    2. [self.view addSubview: (UIView*)appController.unityView];
    3. [self.view sendSubviewToBack: (UIView*)appController.unityView];
    4.  
    Which works, and shows the other interface elements I want on screen but if I segue back to the first view, and back to Unity I get weird scaling and offset issues on the Unity view?!

    I guess the above is equivalent to creating a new UIView as a child in the ViewController but if I do that, then define an outlet and assign UnityView to it I get nothing displayed.

    So thats my epic tale of woe. As you can probably tell I'm quite new to Objective-C and iOS native dev but this feels like I'm a couple of fried synapses away from what I need so any help is appreciated!

    Joe
     
  21. hosepha

    hosepha

    Joined:
    Nov 22, 2012
    Posts:
    22
    Me Again,

    I've been digging into this some more and still have gotten anywhere. I have noticed something odd however...

    As I described I setup the UnityView with addSubView in my custom ViewController. My App has two views, the first a simple button which is wired up to segue to the second with the UnityView.

    The odd bit appears in UnityView layoutSubviews. There is the following code:

    Code (csharp):
    1.  
    2. if (_surfaceSize.width != self.bounds.size.width || _surfaceSize.height != self.bounds.size.height)
    3. {
    4.     _surfaceSize  = self.bounds.size;
    5.     _recreateView = YES;
    6. }
    7.  
    On the first load of the UnityView the _surfaceSize starts at w:768 h:1024. This doesn't match the bounds so it is changed to w:1024 h:768. I guess that makes sense. Its defaulted to portrait, then because thats not the display state it gets fixed to landscape.

    But then, on segue back to first scene and back to Unity, _surfaceSize appears to be right, but the bounds are different resulting in w:1280 and h:512. The UnityView that gets displayed reflects these numbers, squashed vertically by roughly a third and stretched horizontally.

    Then a third attempt results in w:1536 and h 256!

    Any ideas?!
     
  22. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,466
    It is hard to say anything without at least knowing what "proper" extents would be ;-).
    Anyway, two things here:
    indeed i noticed that ios is laying out views in "steps" so it might happen that final layout is not applied immediately. I agree i should look into not recreating gl part on every try but delay till rendering, but oh well.
    second thingy - if you run on retina your bounds will be "non-retina" (yeah i know) so you need to multiply by 2 (contentScaleFactor) if you want to make sense of them. I refer only to you trying to make sense out of numbers - we do handle that thing.
    also - did you try the workaround i posted earlier about externally changing unity view extents do not make impact on rendering resolution
     
  23. hosepha

    hosepha

    Joined:
    Nov 22, 2012
    Posts:
    22
    Thanks for the response Alexey!

    Sorry though, i'm not quite following, what do you mean by proper extents? The resolution I want my game to be at? Its full screen and i'm forcing landscape. Its also not retina so i'm going for w:1024 h:768.

    By your earlier workaround do you mean the modification to layoutSubviews? Here my whole method...

    Code (csharp):
    1.  
    2. - (void)layoutSubviews
    3. {
    4.     [super layoutSubviews];
    5.    
    6.    
    7.     if (_surfaceSize.width != self.bounds.size.width || _surfaceSize.height != self.bounds.size.height)
    8.     {
    9.         _surfaceSize  = self.bounds.size;
    10.         _recreateView = YES;
    11.     }
    12.      
    13.     // ADDED PART
    14.     extern bool _glesContextCreated;
    15.    
    16.     if(_glesContextCreated)
    17.     {
    18.        
    19.         UnityRequestRenderingResolution(_surfaceSize.width * self.contentScaleFactor, _surfaceSize.height * self.contentScaleFactor);
    20.        
    21.         if(_surfaceSize.width > _surfaceSize.height)
    22.            
    23.             UnitySetScreenOrientation(landscapeLeft);
    24.     }
    25. }
    26.  
    I get slightly different behaviours with the added part in and out but neither are right. Without it I get what I described above, where the unity view is offset and stretched. With the code in, again only on the second time I load the UnityView I get something where it appears that the unity view has been scaled uniformly and then game itself is adapting to fit the width (which it is set up to do, I'm just surprised that its working in this context). Incase that isn't clear I've got a pic. I cant show the client project so I've recreated with the help of the internet. The blue is my game camera's background colour.

    I guess this makes sense, its adapting to the resolution its being told. I just don't know where its getting that from?

    Working:
    $workingfine.png


    Not Working:
    $notworking.png
     
  24. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,466
    hm, i can kinda see what you imply, but can you create small repro project and bug report it (drop case number here). I am totally fine with just cat picture as you have issues with views, not with unity itself
    well _surfaceSize member will be used to recreate gl backing later, so thats the source.
    Anyway, please bug report - i am a bit lost on what exactly are you trying to do and what is not working
    P.S. About layoutSubviews fix - since i posted here i fixed it in a way better way for 5.0. It will miss 4.5 - we are so close to release that i dont even want to mention it to release manager, but i will push it to 4.5-based branch so it sees release in some 4.5.x if we have them (and i am sure we will ;-))
     
  25. hosepha

    hosepha

    Joined:
    Nov 22, 2012
    Posts:
    22
    Okay bug report submitted, case: 609768. Give me a shout if it doesn't work!

    Have you got any advice on the other issues I mentioned in the first post? Related to setting up the storyboard to display the unity view? No worries if not, appreciate that you're really busy! Just interested to know about the right way to do it!

    Joe
     
  26. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,466
    Hum, unity part is working like a charm - as to why on layoutSubviews you get such funky extents - no idea. I am too busy right now (well, as everybody else) to dig into storyboards and check what you might do wrong in your setup, so i'll return to it later.
     
  27. devferlara

    devferlara

    Joined:
    Feb 13, 2014
    Posts:
    1
    Hi there,

    Found the solution for the shrink problem of the subView at change to view?, let me know please, Thanks
     
  28. apayne.dev

    apayne.dev

    Joined:
    Nov 3, 2013
    Posts:
    2
    Thanks again for the samples, Alexey!

    For anyone trying to use them with Unity 4.5, after you open the projects in Unity make sure you update the custom app controller scripts in the Assets/Plugins/iOS folders.

    In the NavigationController example, this is MyAppController.mm.

    In the OverlayUI example, this is both MyViewController files (.mm and .h).

    Replace the "iPhone_View.h" import with "UI/UnityViewControllerBase.h"

    (see Alexey's answer at http://forum.unity3d.com/threads/unity-4-5-post-process-build-player-iphone_view-m.248400/ ).
     
  29. nickj09

    nickj09

    Joined:
    Apr 14, 2014
    Posts:
    1
    Hi Alexey, thanks for the explanation of integration part and as well as for the samples. i'll try it on my app, :) cheers
     
  30. QubicSQ2

    QubicSQ2

    Joined:
    Dec 11, 2012
    Posts:
    5
    Hi All.

    Great posting thread here, it helped me a lot!

    So far, since:
    I'm trying in Unity3D 4.5.1 to add an IOS Storyboard (Xcode 6 beta 2) with a simple viewController
    (IFSViewController is a subclass of UIViewController) in my subclass of UnityViewController:

    - (void)createViewHierarchyImpl
    {
    UIStoryboard *storyBoard = [UIStoryboardstoryboardWithName@"MainStoryboard"bundle:nil];
    IFSViewController *viewController = [storyBoard instantiateInitialViewController];
    [viewController setView:_unityView];
    _rootView = viewController.view;
    _rootController = viewController;​
    }​
    I then get an error:
    Thread1: EXC_BAD_ACCESS (code=1, address etc...)

    in:
    iPhone_OrientationSupport.mm

    at:
    void OrientView(UIViewController* host, UIView* view, ScreenOrientation to)
    {
    ScreenOrientation fromController = ConvertToUnityScreenOrientation(host.interfaceOrientation,0);​


    This version below works with a programmatically created NavigationController:

    - (void)createViewHierarchyImpl
    {
    IFSViewController *viewController = [[IFSViewController alloc] init]
    [viewController setView:_unityView];
    IFSNavigationController *nav = [[IFSNavigationController alloc] initWithRootViewController:viewController];
    _rootView = nav.view;
    _rootController = nav;​
    }​
    What goes wrong or am I doing wrong? Or how to implement an IOS Storyboard in this subclassing of UnityViewController?
     
  31. QubicSQ2

    QubicSQ2

    Joined:
    Dec 11, 2012
    Posts:
    5
    FYI
    I also tested the above in Xcode 5.1.1 and got the same error.
     
  32. AnkitoSennin

    AnkitoSennin

    Joined:
    Jul 19, 2012
    Posts:
    1
    Hello intellectuals .Here is the problem:
    I need to develope an iOS app that has a unity3d view inside it.The function of the unity view is visualizing a 3d model that's all.Rest of the app is ios controlled. Now , IOS project is ready with Xcode and Unity also has its own Xcode. I tried to combine both Unity and iOS Xcode by copying all the unity generated Xcode with native IOS code. There were errors where some of the unity generated x code classes had to refer other unity generated classes. This was made possible by adding the .h or .mm headers of the other classes. By doing this I was able to resolve all the errors. But when I try to build the project, I get 200+ linker errors. the sample is given below:

    Undefined symbols for architecture i386: "_UnityADBannerViewWasClicked", referenced from: -[UnityADBanner bannerViewActionDidFinish:] in iAD.o "_UnityADBannerViewWasLoaded", referenced from: -[UnityADBanner bannerViewDidLoadAd:] in iAD.o "_UnityADInterstitialADWasLoaded", referenced from: -[UnityInterstitialAd interstitialAdDidLoad:] in iAD.o "_UnityBlitToSystemFB", referenced from: PreparePresentRenderingSurface(UnityRenderingSurface, EAGLContext) in GlesHelper.o "_UnityCaptureScreenshot", referenced from: PreparePresentRenderingSurface(UnityRenderingSurface, EAGLContext) in GlesHelper.o "_UnityCleanup", referenced from: -[UnityAppController applicationWillTerminate:] in UnityAppController.o "RegisterUnityEngineMeshgetuv()", referenced from: RegisterAllStrippedInternalCalls() in RegisterMonoModules.o "RegisterUnityEngineMeshsetuv()", referenced from: RegisterAllStrippedInternalCalls() in RegisterMonoModules.o "RegisterUnityEnginePinggetip()", referenced from: RegisterAllStrippedInternalCalls() in RegisterMonoModules.o

    For the Information, I have tried the information given by
    http://floored.com/blog/2013/integrating-unity3d-within-ios-native-application.html
    http://alexanderwong.me/post/29949258838/building-a-ios-unity-uiview-uiviewcontroller.
    And it works. It tells to build an unity project and then programme the iOS upon it. But is the opposite possible? That is creating an iOS project and getting unity related files into this project.

    Please let me know if:
    1)Will merging 2 xcode a possible solution.
    2)If yes is this the correct method to do.
    3)why and how are these errors genereting when linking
     
  33. QubicSQ2

    QubicSQ2

    Joined:
    Dec 11, 2012
    Posts:
    5
    Hi AnkitoSennin,

    I in the past used to first make an IOS project and then add the Unity part. I changed my mind, since as Unity and Xcode (IOS) get updates, it became a horror each time to fix things and adjust the compiler settings. In the past I copied the Data Folder, Class Folder, and Library Folder of Unity to my IOS project.
    My conclusion is that my app will need Unity performance, so I use the GUI from IOS (for now) and the graphics power of Unity. Therefor no changes are made in main.mm by using:

    UIApplicationMain(argc, argv, nil, [NSStringstringWithUTF8String:AppControllerClassName]);

    not the subclassing of UnityAppController:

    UIApplicationMain(argc, argv, nil, [NSStringstringWithUTF8String:SubClassOfUnityAppController]);

    This is suggested by previous solutions, links. Now most of these solutions give errors and Unity changes every time it's IOS hybrid options. I hope the subclassing option stays. Also I'm anticipating IOS Metal and Swift and therefor not putting much effort in understanding or tweaking of the Unity code for IOS.
    My approach:
    - 1 Get the basic Unity part and build this for IOS.

    - 2 Subclass UnityAppController and use the - (void)createViewHierarchyImpl method to add IOS functionality, like storyboards and build IOS from there.

    - 3. Transfer from an original Xcode project the files into the Xcode project (made by Unity) and copy them.

    - 4. Tag the copied .m classes from the original Xcode project (except for the subclass of UnityAppController) in build Phases under Compiled Resources with -fobjc-arc (this should enable ARC, automatic reference counting for these objective-C files).


    In order to solve the problem with Storyboards in - (void)createViewHierarchyImpl, I'm currently testing to first create a UINavigationController with initwithrootviewcontroller which in itself is an instantiated initial view controller from a loaded Storyboard. Then use segues for going to other parts in the Storyboard. Then pop and push other view controllers or other Storyboards from that UINavigationController.
    At least the Unity code doesn't complain; now _rootCoontroller has a real view controller (using a Storyboard here didn't work in my code, see my previous post).

    - (void)createViewHierarchyImpl
    {
    UIStoryboard *storyboard = [UIStoryboardstoryboardWithName@"MainStoryboard"bundle:nil];
    UIViewController *vc = [storyboard instantiateInitialViewController];
    IFSNavigationController* navVC = [[IFSNavigationController alloc] initWithRootViewController:vc];
    [navVC.topViewController.view insertSubview:_unityView];

    _rootView = navVC.view;
    _rootController = navVC;​
    }

    One can make public properties of _unityView/storyboards/viewControllers in the subclass version of UnityAppController, so other Objective-C code can access them. Hope this approach will work for me and for you.

    Yes, it is troublesome and not easy, so I make many backups.
     
  34. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    Hi,
    After following the sample codes in this thread, I was able to integrate my unity app inside iOS app and use it with story boards. It seems to work fine.
    When in the Unity view, if I change the iPad orientation from Portrait to Landscape, the content get stretched. They don't get resized properly and vice versa.
    But if I run my unity app directly in the iPad without integrating with the iOS app, then when the iPad orientation changes, the content get properly resized according to the orientation.
    Please tell me how I can fix this issue after integrating with the iOS app.

    Thanks
     
  35. QubicSQ2

    QubicSQ2

    Joined:
    Dec 11, 2012
    Posts:
    5
    Hi Madhur,

    I had the same problem in the past, what I then tried is to let the UIView containing Unity to be at the root of all view controllers. Then on top of that I instantiated new storyboards or view controllers. So the Unityview never gets instantiated twice and is always there. Then all responses in orientation also get to that view.
    Trouble is I only use an iPhone 4S, so I don't know how this differs from an iPad.
     
  36. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    Thanks QubicSQ2.
    Can you please share the code part you did that.
     
  37. Roozbeh

    Roozbeh

    Joined:
    Jun 7, 2013
    Posts:
    1
    Fellas,
    I had the same problem:
    Thread1: EXC_BAD_ACCESS (code=1, address etc...)
    in:
    iPhone_OrientationSupport.mm

    at:
    void OrientView(UIViewController* host, UIView* view, ScreenOrientation to)
    {
    ScreenOrientation fromController = ConvertToUnityScreenOrientation(host.interfaceOrientation,0);
    Finally, I've realized, UnityAppDelegate.m file mistakenly marked as "-fno-objc-arc", so the view controller object initialized in the function was being released after "createViewHierarchyImpl" being called.

    I thought this might worth sharing ...
     
  38. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    Thanks all for your help.
    I got my issue solved by adding this line in my iOS code.

    UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
    UnitySetScreenOrientation(deviceOrientation);
     
  39. masha

    masha

    Joined:
    Aug 20, 2012
    Posts:
    8
    Hi,

    I was wondering if anybody else here encountered the same issue as me.

    I had managed to set up the unity view inside of a native view controller using storyboards and Unity 4.3. When I updated to Unity 4.5, I replaced the necessary imports in my UnityAppController subclass and made sure to recreate the Xcode project from scratch to have all the correct unity stuff.

    I now get an EXC_BAD_ACCESS error from AppControllerClassName when calling UIApplicationMain(). AppControllerClassName points to complete garbage...

    It might be worth mentioning that I'm using arc in my UnityAppController subclass by setting the -fobjc-arc flag in the compile sources project settings.

    Any help would be really appreciated,
    Thanks!


    SOLVED:
    Turned out the issue was having my storyboard set in the Target Summary Settings. Unless you clean your project, it kinda stays there even once deleted... >< my bad
     
    Last edited: Jul 22, 2014
  40. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,466
    >> I now get an EXC_BAD_ACCESS error from AppControllerClassName when calling UIApplicationMain(). AppControllerClassName points to complete garbage...

    please submit bug repro with small repro case
     
  41. masha

    masha

    Joined:
    Aug 20, 2012
    Posts:
    8
    Hi Alexey,

    I can run your NavigationControllerSample fine with the latest version of Unity so I'm pretty sure the issue is on my end and not Unity's/

    EDIT:
    Solved the issue, as I guessed, it was completely my bad. Posted the solution in case anybody encounters it.
     
    Last edited: Jul 22, 2014
  42. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    Hi,

    I have a iOS app(with a Story board) which has a Unity app integrated to it, which was done by following the samples given in this thread. My first two views are iOS views in story board, in the third view I am showing the Unity view like below.
    Everything works fine. Now I want to show a iOS view on top of this Unity view in some situations. (e.g. I want to show a image using iOS controls on a button click while on this unity view)
    Can some one please tell me how to do that? Any code snippet for that will be really helpful.
    Thanks.

    Code (csharp):
    1.       UnityAppController *unityController = (UnityAppController*) [[UIApplication sharedApplication] delegate];
    2.              
    3.         uiView = (UIView*)unityController.unityView; // get the view
    4.      
    5.         [uiView setFrame:[[UIScreen mainScreen]applicationFrame]]; // set the Framesize
    6.        
    7.         [self.view addSubview: uiView];      
    8.      
    9.         [unityController unityPause:NO];
     
  43. thenerd

    thenerd

    Joined:
    Aug 6, 2014
    Posts:
    6
    Hi,

    I've collected all the tips from this post and put it in a tutorial for people who are still struggling with this.
    I had the same issue to put a single Unity layer in a native app.

    Hope this can help some of you guys out!
    http://www.the-nerd.be/2014/09/08/sandbox-unity-app-in-existing-ios-app/

    I've also put my code on GitHub, so you can check it out there as well (link is in the blog post)

    Cheers,
    Frederik
     
    Last edited: Dec 1, 2014
    mdrotar likes this.
  44. TedB

    TedB

    Joined:
    Aug 26, 2012
    Posts:
    7
    This has been a very helpful thread. I successfully integrated a UINavigationController with Unity 4.3. Upon upgrading to 4.5.3, there is a problem with orientation changes.

    My app previously changed orientation for each of the four orientations nicely. Now, the screen goes black when I change from Portrait home button on bottom to any other orientation. Or, if I start the app in any other orientation than that, the screen goes black after the Unity splash goes away. When the screen is black, audio is still playing. But I can't get the screen to display again, even when exiting and resuming the app.

    I saw a line of code madhur shared above that looked related, but I am not sure if that will solve the problem, and where I should put it. How can I fix this problem?

    Here is my custom AppController, myAppController.mm:


    Code (objectiveC):
    1.  
    2. @interface MyAppController : UnityAppController
    3. {
    4.     UINavigationController*        _navController;
    5.     UIViewController*            _embedController1;
    6.     UIViewController*            _embedController2;
    7.     UIViewController*            _embedController3;
    8. }
    9. - (void)createViewHierarchyImpl;
    10. @end
    11.  
    12. @implementation MyAppController
    13. - (void)createViewHierarchyImpl;
    14. {
    15.  
    16.     _rootController    = [[UnityDefaultViewController alloc] init];
    17.     _rootView        = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    18.     _rootController.view = _rootView;
    19.    
    20.     _embedController1 = [[UIViewController alloc] init];
    21.     _embedController1.view = _unityView;
    22.     _embedController1.navigationItem.rightBarButtonItem =
    23.     [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:self action:@selector(showSettings:)];
    24.  
    25.     _embedController2 = [[TestViewController alloc] initWithNibName:nil bundle:nil];
    26.     _embedController2.navigationItem.leftBarButtonItem =
    27.     [[UIBarButtonItem alloc] initWithTitle:@"Game" style:UIBarButtonItemStyleBordered target:self action:@selector(moveLeft:)];
    28.     _embedController2.navigationItem.rightBarButtonItem =
    29.     [[UIBarButtonItem alloc] initWithTitle:@"More" style:UIBarButtonItemStyleBordered target:self action:@selector(showMore:)];
    30.    
    31.     _embedController3 = [[PurchaseTablewViewViewController alloc] initWithNibName:nil bundle:nil];
    32.     _embedController3.navigationItem.leftBarButtonItem =
    33.     [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:self action:@selector(moveLeft:)];
    34.     _embedController3.navigationItem.rightBarButtonItem =
    35.     [[UIBarButtonItem alloc] initWithTitle:@"Restore Purchase" style:UIBarButtonItemStyleBordered target:[PurchaseTablewViewViewController sharedManager] action:@selector(restoreTapped:)];
    36.  
    37.    
    38.     _rootController.view = _rootView;
    39.    
    40.     _navController = [[UINavigationController alloc] initWithRootViewController:_embedController1];
    41.     _navController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
    42.     [_rootView addSubview:_navController.view];
    43.    
    44. }
     
  45. thenerd

    thenerd

    Joined:
    Aug 6, 2014
    Posts:
    6
    Last edited: Dec 1, 2014
  46. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,466
    @thenerd yay for explaining stuff 8)
    some explanaitons to pain points
    1. 4.5 indeed does need -fno-objc-arc. For 5.0 we enabled ARC and fixed trampoline
    2. About changing xcode project, for 5.0 we did actually thought about it ;-)
    https://bitbucket.org/Unity-Technologies/xcodeapi
    in 5.0 it should be included already but it should be possible to use it in 4.5 (though i dont have directions yet)
    So this should be solved easier soon
     
  47. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,117
    don't use [UIScreen bounds] in -loadView
    this might/will pose problems on iOS 8+
    https://devforums.apple.com/message/1029011
    the proper spot for layout and obtaining current size/s in view hierarchy seems to be -willLayoutSubviews
     
    Last edited: Sep 8, 2014
  48. EasonUnity

    EasonUnity

    Joined:
    Sep 25, 2014
    Posts:
    1
    why I did not found "UnityAppController",someone know?
     
  49. Juice118

    Juice118

    Joined:
    Dec 12, 2011
    Posts:
    10
    Hey guys,
    With thanks to this thread and people that have posted I was successful in getting unity working as a view in a native project with storyboard and navigation controller using Unity 4 and Xcode 5.

    I have since commenced a new project and have been unable to get the same working having upgraded to Xcode 6 and Unity 4.5.

    I am getting a bad access error at:
    UIApplicationMain(argc, argv, nil, [NSStringstringWithUTF8String:AppControllerClassName]);
    in main.mm

    I had written notes (very basic) to myself when I had it working and the steps I have followed are:

    1. Build iOS version of Unity project via Unity.
    2. Open Build in Xcode.
    3. Create a StoryBoard and add it to the Plist as Main Story Board File Base
    4. In storyboard create your Navigation controller and UIViewControllers (one will need to be your game view)
    5. Open up Appcontroller and over copy (note this is now in UnityAppController (ViewHandling))

    Code (CSharp):
    1. - (void)createViewHierarchyImpl
    2. {
    3.     UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle: nil];
    4.  
    5.     UIViewController *mainVC    = [mainStoryboard instantiateInitialViewController];
    6.     _rootController    = [[UnityDefaultViewControlleralloc] init];
    7.     _rootView     = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    8.     [_rootView addSubview : mainVC.view];
    9. }
    //Remember to change the storyboard name in this

    6. Create a new file (.h and .m) This will be your unity controller.
    7. In ViewDid load of the new file add:

    Code (CSharp):
    1. #import "UnityAppController.h"
    2.  
    3. - (void)viewDidLoad
    4. {
    5.     [superviewDidLoad];
    6.  
    7.     // Do any additional setup after loading the view.
    8.     UnityAppController *appController = (UnityAppController*) [[UIApplicationsharedApplication] delegate];
    9.     self.view = (UIView*)appController.unityView;
    10. }
    //Note if you do not do this step and attempt to assign the view as unity view via storyboard then touch inputs will not work.

    8. In UnityView.m add: (step no longer required)

    Code (CSharp):
    1. - (void)layoutSubviews
    2. {
    3.     if (_surfaceSize.width != self.bounds.size.width || _surfaceSize.height != self.bounds.size.height)
    4.     {
    5.         _surfaceSize  = self.bounds.size;
    6.         _recreateView = YES;
    7.     }
    8.   [super layoutSubviews];  // This is the line to add.
    9. }

    9. If you get sigbart error on main.mm may need to change: (error happens with either of the below)

    //UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]); //to
    UIApplicationMain(argc, argv, nil, @"UnityAppController");

    10. In UnityAppController.h add: (no longer required)
    @property (strong, nonatomic) UIWindow *window;


    These are the only steps I have taken and I cannot seem to work out where I am going wrong or the cause of the error at:
    UIApplicationMain(argc, argv, nil, [NSStringstringWithUTF8String:AppControllerClassName]);

    Thanks,
     
  50. QubicSQ2

    QubicSQ2

    Joined:
    Dec 11, 2012
    Posts:
    5
    Alexey, there are some issues now in Unity 5 beta 14 which have to do with the UIViewControllers; at least in UnityViewControllerBase.mm method:
    ViewWillTransitionToSize_DefaultImpl uses
    interfaceOrientation and this is deprecated as of IOS 8, while it is still being used within
    #if UNITY_IOS8_ORNEWER_SDK.

    Also these two:
    extern "C" void AddViewControllerRotationHandling (Class class_,

    IMP willRotateToInterfaceOrientation,

    IMP didRotateFromInterfaceOrientation,

    IMP viewWillTransitionToSize);



    extern "C" void AddViewControllerDefaultRotationHandling (Class class_);

    give Parse Issue Errors: "Expected identifier or '('

    I tested this with Xcode 6.1.1 (beta) and iOS 8.1.1 while subclassing UnityAppController and including in that subclassed .h file:
    #include "UI/UnityView.h"
    #include "UI/UnityViewControllerBase.h"
    (the only includes used in my project for UnityView.h and UnityViewControllerBase.h)

    Hopefully it gets fixed. Great that ARC is working in 5.0!!!
     
unityunity