iOS ViewController Hierarchy changed with Unity 4.6.5 and Vuforia 4.2 update

755 Views Asked by At

I have an app that consists of Xcode Storyboard UI and a hosted Unity3D/Vuforia project for one of the views. I was previously using Unity 4.6.2 and Vuforia 3.0.9 and had implemented an UnityAppDelegate subclass with the following method that allowed me to do this.

-(void)createViewHierarchyImpl
{
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"AR" bundle:nil];
    PPARStartViewController * helloVC = (PPARStartViewController *)[sb instantiateViewControllerWithIdentifier:@"StartController"];

    self.navController = [[UINavigationController alloc] initWithRootViewControllier:helloVC];
    self.navController.navigationBarHidden = YES;

    _rootController = self.navController;
    _rootView = self.navController.view;

}

I also wrote an Extension to UINavigationController to handle rotation changes further down my view stack (loading different images depending on orientation).

However, I have had to update my app to use Unity3D 4.6.5 and Vuforia 4.2 due to the 64bit requirement for submitting apps to the App Store. This has caused a couple of issues.

  1. The above createViewHierarchyImpl method no longer works in that state. It was throwing a runtime error:

Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:PPARStartViewController: 0x17dc3070 should have parent view controller:UnityDefaultViewController: 0x1c083200 but actual parent is:UINavigationController: 0x17dc3820’

I have had to change it to the following:

    -(void)createViewHierarchyImpl
    {
        _rootController = [[UIViewController alloc] init];
        _rootView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        _rootController.view = _rootView;

        UIStoryboard *sb = [UIStoryboard storyboardWithName:@"AR" bundle:nil];
        PPARStartViewController * helloVC = (PPARStartViewController *)[sb instantiateViewControllerWithIdentifier:@"StartController"];

        self.navController = [[UINavigationController alloc] initWithRootViewController:helloVC];
       [_rootView addSubview:self.navController.view];

       self.navController.navigationBarHidden = YES;
    }
  1. Doing the above changes the Hierarchy from before, and my UINavigationController extension class no longer catches the rotation calls. They are now being caught by the UnityDefaultViewController. I tried extending this class in the same way, but at run time that view controller appears to have no children, parents or any relationship with the views currently loaded.
  2. Finally, and possibly unrelated but I'm sure it may be, the Vuforia view is not rotating correctly. Portrait and LandscapeLeft are fine, but in LandscapeRight and PortraitUpsidedown the camera feed is flipped.

Solutions I'm hoping for:

  1. Ideally I'm hoping someone can tell me that my original code for question 1 is possible and I'm just missing something that fixes the parental relationship of my view controllers.
  2. If not, then I need to find out how to pass the Rotation notifications down from the UnityDefaultViewController to my UINavigationController.
  3. And finally, is there a way to stop the UnityPlayer view rotating? There is nothing in it other than camera feed and augmented content, so the actual view doesn't even need to rotate.
1

There are 1 best solutions below

0
On BEST ANSWER

Looking into the UnityAppController+ViewHandling.mm and comparing it with the old version from pre Unity 4.6 I was able to come up with a solution.

In VuforiaNativeRendererController.mm I also implemented the createAutorotatingUnityViewController method. In here I return a new instance of UnityDefaultViewController (this is what createViewHierarchyImpl used to do).

-(UIViewController*)createAutorotatingUnityViewController
{
    return [[UnityDefaultViewController alloc] init];
}

Then in UnityAppController.mm I removed the code from the new checkOrientationRequest method, and in onForcedOrientation swapped the

[self transitionToViewController:[self createRootViewController]];

to the old way of:

OrientView(_rootController, _rootView, orient);
[_rootView layoutSubviews];

After all this I was able to use my original code for createViewHierarchyImpl and retain control over my rotations.

The AR camera view is still flipped in some rotations, but I now believe that to be a separate issue.

[EDIT] I figured out why the AR camera view was not orientating. I needed to pass the rotation notifications to the viewcontroller that held the UnityView as a sub view and then call

[subView willRotateTo:ConvertToUnityScreenOrientation(toInterfaceOrientation, 0)]; 

now all rotations are working as intended. :)