Search Unity

Can't get LaunchScreen.storyboard to work! Need docs.

Discussion in 'iOS and tvOS' started by tessellation, Apr 3, 2018.

  1. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    Unity 2017.3.1p3 copies my storyboard to the Xcode project, but there doesn't seem to be a way to include images in an xcassets folder. When I manually add the xcassets in Xcode, the launch screen storyboard appears correctly, but Unity crashes on startup:

    Uncaught exception: NSInvalidArgumentException: Storyboard (<UIStoryboard: 0x1664c580>) doesn't contain a view controller with identifier 'unitySplashStoryboard'

    0 CoreFoundation 0x21a29b23 <redacted> + 150
    1 libobjc.A.dylib 0x211e6dff objc_exception_throw + 38
    2 UIKit 0x267143d9 <redacted> + 0
    3 GameAppName 0x00049ff4 _Z16ShowSplashScreenP8UIWindow + 548
    4 GameAppName 0x0006d3cc -[UnityAppController(ViewHandling) createUI] + 2160
    5 GameAppName 0x000698f0 -[UnityAppController application:didFinishLaunchingWithOptions:] + 1856


    Can someone from Unity please document how to make this work? Thanks!
     
  2. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
  3. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    I've been digging into this some more by looking at the Unity source code in XCode. What it looks like to me is that in the SplashScreen.mm code, ShowSplashScreen() wants a UIViewController with ID 'unitySplashStoryboard' so I added that to my storyboard. That fixes the first crash above, but then it crashes in ShowSplashScreen() a few lines later when it calls [_controller create: window] because UIViewController doesn't contain the 'create' selector. It clearly is looking for _controller to be a SplashScreenController instance, but it isn't possible to assign custom classes (like SplashScreenController) to LaunchScreen storyboards, so I don't get how this code is supposed to work?
     
    cloutiertyler likes this.
  4. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
  5. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    This doesn't sound familiar. Are you able to file a bug report so I can look into it?
     
  6. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    Thanks @karl_jones ! - Yes, I filed a bug, the fogbugz number is 1023109

    I included a LaunchScreen.storyboard and xcassets with images for it with the bug post.

    Hopefully there's a fix I can make in the IOS Trampoline source (i.e. Classes/UI) so I don't have to wait for an official patch. :)
     
    cloutiertyler and karl_jones like this.
  7. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    Hi @karl_jones, did that bug post have enough information?
     
  8. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    Its with QA at the moment. Looks like they have been discussing it with you via email.
     
  9. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    @karl_jones, yes, they've reproduced it and passed it on to the engineers.
     
    karl_jones likes this.
  10. Masterfalcon

    Masterfalcon

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    364
    Out of curiosity, if you make your storyboard controller have a custom class of SplashScreenController with storyboard ID unitySplashStoryboard does it work as expected? I've attached a screen shot for reference.

    There were supposed to be some docs for this but they must have fallen through the cracks. I'll see what I can do about that.
     

    Attached Files:

    karl_jones likes this.
  11. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    No that doesn't work because storyboards do not allow custom classes.

    Thanks, that would be very helpful!
     
    cloutiertyler likes this.
  12. Masterfalcon

    Masterfalcon

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    364
    True, but the view controller instance in your storyboard does allow custom classes.
     
  13. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    I'm not sure what your point is. If you try to compile with that storyboard using a custom class as a launch screen storyboard, you'll get an error. My experience is that launch storyboards only work with core classes, like UIViewController. It will not work with a derived custom class.
     
    cloutiertyler likes this.
  14. Masterfalcon

    Masterfalcon

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    364
    I've done some work on this and your changes to ShowSplashScreen() are absolutely right.

    In SplashScreen.mm, ShowSplashScreen() should look like this:


    void ShowSplashScreen(UIWindow* window)
    {
    _controller = [[SplashScreenController alloc] init];

    [_controller create: window];
    [window makeKeyAndVisible];
    }


    Further, make sure that iPhone and iPad Launch Screen type is set to None in the Splash Screen section of the PlayerSettings Inspector.
     
    DistortionFactor likes this.
  15. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    Thanks @Masterfalcon - while that fixes the crash, I don't think that's the expected solution because then there's a black screen after this and before the Unity Splash screen. I noticed there is code elsewhere in the Unity IOS startup code (I don't recall where at the moment) - where it tries to display the storyboard. This is a good thing as I think it's trying to avoid having a black screen by displaying the Launch Storyboard again. However, I believe this code to display the Launch Storyboard again is broken. The fix above avoids this code, but that is not ideal.

    Also there's no way to have xcasset images with your Storyboard. Unity needs to find and copy those associated assets to the IOS (XCode) project folder and add it to the XCode solution/project file.
     
  16. Masterfalcon

    Masterfalcon

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    364
    Which other code do you see that is a problem?

    I think the xcasset bundle thing is a separate issue, I'll it discuss with the team.
     
  17. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    Sorry, in that method ShowSplashScreen, it creates the view controller from the storyboard to avoid that black screen. Elsewhere above in the SplashScreen class, it checks if the storyboard is being used and it doesn't show the Launch Images or "nib" file alternative. If you remove that code as you suggest in ShowSplashScreen, then you get black after the Storyboard launch screen, which looks bad.
     
  18. owiesniak

    owiesniak

    Joined:
    Jan 27, 2018
    Posts:
    6
    I'm facing the same problem. Changing `ShowSplashScreen` as Masterfalcon mentioned above works (application is booting again) but it does not look good because it is immediate fading to black.
     
  19. Masterfalcon

    Masterfalcon

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    364
    I actually have a fix for that as well. I'm attaching a diff that you can apply to SplashScreen.mm to fix both issues.
     

    Attached Files:

  20. WereVarg

    WereVarg

    Joined:
    Apr 9, 2012
    Posts:
    20
    Any ETA when it will be in the release versions?
     
    cloutiertyler likes this.
  21. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    @Masterfalcon Will this be included in the LTS releases? 2017.4?
     
  22. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,791
    I've stumbled upon this as well. It's still not fixed in Unity 2018.1.6f1.

    I've been happily using the simple iPhone/iPad Launch screens, until I found out that they cause Screen.safeArea to return wrong values for some reason ( Case 1052565 ). So I tried the built in Unity Splash Screen stuff, but I don't want it to fade in and out, and 2 seconds it too long and it seems that I can't set it to be shorter than that.

    So I thought I'd create a Storyboard and use that. So I made it, added it to my Unity project and then I was stumbled as to how I'd also add an image to go with it in the build. Seems it isn't possible (?). So I added the image manually and it also crashed for me.

    Then I came here.

    I applied the patch posted here, and even though it works now, it seems it doesn't handle the orientation correctly.

    I have the orientation set only for landscape in the General settings and it's set to only landscape in info.plist. But still, if I have my iPhone 6S Plus in portrait when I launch my app, the storyboard I provided switches to portrait for half a second, which is annoying and looks weird.

    I have to say it has been frustrating that none of the built in methods that Unity provides work correctly for me.
     
    WereVarg likes this.
  23. plasticYoda

    plasticYoda

    Joined:
    Aug 20, 2013
    Posts:
    62
    So I upgraded a project to Unity2018.3 that had a working storyboard splash screen and got the following exception on launch:

    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Application windows are expected to have a root view controller at the end of application launch'

    I switched to a simple test project, and copied my storyboard over and I get the same error. After some further testing and tweaking, I've discovered that by replacing this line:

    _controller = [storyboard instantiateInitialViewController];

    with

    _controller = [storyboard instantiateViewControllerWithIdentifier: @"unitySplashStoryboard"];

    in SplashScreen.mm.

    The line came from the previously working SplashScreen.mm as part of Unity2017.

    The app will launch and show the storyboard as expected. Can anyone @Unity or @Masterfalcon illustrate how this is supposed to work?
     
  24. Masterfalcon

    Masterfalcon

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    364
    In either project is your storyboard viewcontroller set as the Initial View Controller in Xcode?
     
  25. plasticYoda

    plasticYoda

    Joined:
    Aug 20, 2013
    Posts:
    62
    In the 2nd test project, everything is as default in Unity2018.3, except I checked the 'use storyboard' option in the build settings, created a storyboard file (used previously working storyboard from my 2017 project, less the background image), and then modified the SplashScreen.mm file as per my previous post after building the project once.

    So I don't explicitly set the initial ViewController, its just whatever the normal unity launcher does.
     
  26. Masterfalcon

    Masterfalcon

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    364
    Ah ok. I think what you'll want to do(I haven't tried this yet today) is select the View Controller in your storyboard and set Use as Launch Screen(see the first screenshot). Then also check Is Initial View Controller (second screenshot). Hopefully that will do the trick.
     

    Attached Files:

  27. plasticYoda

    plasticYoda

    Joined:
    Aug 20, 2013
    Posts:
    62
    That let the standard 2018.3 code launch without error. I had to recreate a new storyboard file, the one I'd used previously had a custom class name, and that was generating an error. Also, the storyboard must be called "LaunchScreen.storyboard" and I had to manually add it to the XCode project generated by Unity.

    However, this should let me upgrade to 2018.3.

    Thanks.
     
  28. Zilppuri

    Zilppuri

    Joined:
    Mar 15, 2015
    Posts:
    8
    Yeah the whole splash-image setup is really bad in Unity. I though that they would eventually figure it out.

    The recommended way by Apple to do LaunchScreens is to use Storyboard. Still even if you do this, Unity will copy the default Splash-images to the project, causing Warnings.
    No biggue, Unity on iOS is a deprecation-fest anyway :D

    The biggest issue as AcidArrow mentioned is the orientation. If you have a game running in Landscape only, the splash will still display briefly on Portrait.
    This is becase UnityAppController calls the Splash-ViewControllers supportedInterfaceOrientationsForWindow for determining where to orient.
    Unity (for reasons) checks if your project has a Storyboard called "LaunchScreen" and then creates the first ViewController on that. Since this is simply a default UIViewController, it will return ALL of the orientations as supported.

    To fix this you could simply create a custom UIViewController derived Class where you override this method:

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations
    {
    UIInterfaceOrientationMask ret = 0;
    ret |= (1 << UIInterfaceOrientationLandscapeRight);
    ret |= (1 << UIInterfaceOrientationLandscapeLeft);
    return ret;
    }

    However, on XCode you are not able to set a custom UIViewController for LaunchScreen-Storyboards.
    For this we need to duplicate the Storyboard. The other is actually used by iOS as LaunchScreen and the other is a "decoy" for Unity to display for that weird 1 second.

    So the "fix" is:
    0. In Unity, set the Splash image to "NONE"
    1. Create a new Obj-C (or swift if youwant) UIViewController Cocoa Class and add the above supportedInterfaceOrientations method. Name this class "CustomSplashViewController" or whatever.
    1. Duplicate your LaunchScreen.storyboard and name it something like ActualLaunchScreen.storyboard
    2. In original LaunchScreen.storyboard, open the file in XCode interface editor and set the Custom class to CustomSplashViewController
    -> Unity will blindly look for LaunchScreen.storyboard (instead of determining the actual iOS Launch Screen) and use our custom class for that < 1 sec weird splash they just have to do.
    3. In your Project Target settings (XCode) set the LaunchScreenFile to the "ActualLaunchScreen"
    -> iOS will use this file without the custom class

    Now after you have your screen setup, you ideally will want to automate setting the project.
    So copy the CustomSplashViewController.m, CustomSplashViewController.h, ActualLaunchScreen.storyboard and LaunchScreen.storyboard files to your Assets/Editor folder.
    And then in your PostProcessing methods copy the files and setup values. Here is a basic (untested) gist: https://gist.github.com/zilppuri/25514d9eb30283e372b86000482042f4
     
  29. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    Have you filed a bug report? We could fix this.
     
  30. Petr777

    Petr777

    Joined:
    Nov 8, 2017
    Posts:
    49
  31. Petr777

    Petr777

    Joined:
    Nov 8, 2017
    Posts:
    49
  32. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    We are aware of the April deadline and are looking into the issue at the moment.
     
    Petr777 likes this.
  33. smartinetz

    smartinetz

    Joined:
    Dec 8, 2017
    Posts:
    49
    Using Unity Pro 2019.2 my splash screen does not show up on iOS anymore either.
    Not sure if this ever gets fixed or if I have to wait for the 2020 update!?!?!? :(

    Really frustrating!!
     
  34. StuWebstMW

    StuWebstMW

    Joined:
    May 1, 2015
    Posts:
    1
    These are the build warnings we were getting even with the 'Use Storyboard for Launch Screen' player setting enabled:
    Code (Log):
    1. warning: Launch images are deprecated in iOS 13.0. Use a launch storyboard or XIB instead.
    2. warning: 'UILaunchImages' has been deprecated, use launch storyboards instead.
    Clearing the Unity-iPhone target’s 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME' build setting seems to be the solution.


    There's also a quirk if you want the app to launch with the status bar hidden. The current setup will initially launch with the status bar hidden. When Unity swaps to a new instance of the storyboard view controller, the status bar will be visible. Then when the splash screen flow is done, the status bar will be hidden again.

    To fix this, the CustomSplashViewController (from your example) needs to handle prefersStatusBarHidden e.g.:
    Code (Objective-C):
    1. - (BOOL)prefersStatusBarHidden
    2. {
    3.     // copied from UnityViewControllerBase+iOS.mm
    4.     static bool _PrefersStatusBarHidden = true;
    5.  
    6.     static bool _PrefersStatusBarHiddenInited = false;
    7.     if (!_PrefersStatusBarHiddenInited)
    8.     {
    9.         NSNumber* hidden = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"UIStatusBarHidden"];
    10.         _PrefersStatusBarHidden = hidden ? [hidden boolValue] : YES;
    11.  
    12.         _PrefersStatusBarHiddenInited = true;
    13.     }
    14.     return _PrefersStatusBarHidden;
    15. }
    To prevent a status bar flicker during the swap, comment out [_window makeKeyAndVisible] in UnityAppController+ViewHandling.mm in this method:
    Code (Objective-C):
    1. - (void)createUI
    2. {
    3.     NSAssert(_unityView != nil, @"_unityView should be inited at this point");
    4.     NSAssert(_window != nil, @"_window should be inited at this point");
    5.  
    6.     _rootController = [self createRootViewController];
    7.  
    8.     [self willStartWithViewController: _rootController];
    9.  
    10.     NSAssert(_rootView != nil, @"_rootView  should be inited at this point");
    11.     NSAssert(_rootController != nil, @"_rootController should be inited at this point");
    12.  
    13.     //[_window makeKeyAndVisible]; // this line here; makeKeyAndVisible gets called in ShowSplashScreen with our CustomSplashViewController
    14.     [UIView setAnimationsEnabled: NO];
    15.  
    16.     // TODO: extract it?
    17.  
    18.     ShowSplashScreen(_window);
    19.  
    20. #if UNITY_SUPPORT_ROTATION
    21.     // to be able to query orientation from view controller we should actually show it.
    22.     // at this point we can only show splash screen, so update app orientation after we started showing it
    23.     // NB: _window.rootViewController = splash view controller (not _rootController)
    24.     [self updateAppOrientation: ConvertToIosScreenOrientation(UIViewControllerOrientation(_window.rootViewController))];
    25. #endif
    26.  
    27.     NSNumber* style = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"Unity_LoadingActivityIndicatorStyle"];
    28.     ShowActivityIndicator([SplashScreen Instance], style ? [style intValue] : -1);
    29.  
    30.     NSNumber* vcControlled = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"UIViewControllerBasedStatusBarAppearance"];
    31.     if (vcControlled && ![vcControlled boolValue])
    32.         printf_console("\nSetting UIViewControllerBasedStatusBarAppearance to NO is no longer supported.\n"
    33.             "Apple actively discourages that, and all application-wide methods of changing status bar appearance are deprecated\n\n"
    34.         );
    35. }
     
  35. Petr777

    Petr777

    Joined:
    Nov 8, 2017
    Posts:
    49
  36. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    Petr777 likes this.
  37. Petr777

    Petr777

    Joined:
    Nov 8, 2017
    Posts:
    49
    Can you say please are there any other issues related to April storyboard deadline that Unity team plan to fix, that not fixed yet?
     
  38. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    Petr777 likes this.
  39. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,791
    With Unity’s maddening refusal to fix even the most trivial things without a user donating their time submitting a bug report, I wouldn’t count on anything getting fixed before April.

    I fully expect to need to do weird ass workarounds to make storyboards work properly.
     
  40. chico_barnstorm

    chico_barnstorm

    Joined:
    Jun 11, 2014
    Posts:
    10
    @karl_jones We have been using storyboards for some time now, and they used to work fine up to Unity 2018.4.17f1 (FWIW only supported portrait orientation). However, after updating to Unity2018.4.18f1, the splash screen automatically fades to black now. Is this a known issue?
     
  41. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    Im not sure. Can you please file a bug report?
     
  42. andersTheNinja

    andersTheNinja

    Joined:
    May 17, 2018
    Posts:
    18
    Same here, except I'm on 2019.3.7f1. Did you file a bug report?
    Also, I'm getting these errors in device log:
    2020-04-03 09:01:29.626154+0200 ios[58959:16000091] Unbalanced calls to begin/end appearance transitions for <SplashScreenController: 0x12dc03610>.
     
  43. Petr777

    Petr777

    Joined:
    Nov 8, 2017
    Posts:
    49
    @andersTheNinja
    Try to remove .storyboard extension from value of UILaunchStoryboardName in Info.plist
     
  44. WermHat

    WermHat

    Joined:
    Jul 13, 2012
    Posts:
    88
  45. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
    It should be in 2017.4.38
    Waiting for QA to verify it before the issue tracker is updated
     
    WermHat likes this.
  46. CaptJim

    CaptJim

    Joined:
    Oct 28, 2016
    Posts:
    31
    @karl_jones Could I ask, is 2017.4.38 the earliest appearance of Unity support for Storyboard, or has it been available in earlier versions? And if so will those versions be issued/patched with this fix?
     
  47. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,291
  48. WermHat

    WermHat

    Joined:
    Jul 13, 2012
    Posts:
    88
    FWIW the fix in this thread can be combined with some tinkering to get storyboards working seamlessly as far back as Unity 5. If you want some help with a U5 implementation, send me a PM
     
    CaptJim likes this.
  49. benbenmushi

    benbenmushi

    Joined:
    Jan 29, 2013
    Posts:
    34
    ^ This solved the issue for me on 2017.4.27
     
  50. Numa

    Numa

    Joined:
    Oct 7, 2014
    Posts:
    100
    So if we have to add a postbuild script to copy the files and set the storyboard as launch screen, as well as set the splash image to None..

    what does the "Use custom storyboard button" actually do?

    It doesn't seem to do anything at all for me. Am I missing something?
    Unity 2019.2.21

    Thanks!