DavidPeicho / unity-swiftui-example

Integration example of the Unity engine in a SwiftUI-based application
MIT License
71 stars 16 forks source link

Solution for Unity doesn't render #13

Open bdeweygit opened 1 year ago

bdeweygit commented 1 year ago

From the README

Between the moment you create the UnityFramework instance, and the moment you can display it, it seems like there is an issue. Some people try to add a delay, but this is definitely a hack.

The problem is a race condition. In public func show(controller: UIViewController) we add Unity's rootView as a subview of our own custom view controller, but when we start running Unity it will automatically add it as a subview of its own internal view controller. One overrides the other, so whoever runs last wins. Maybe you can find some way to wait for Unity to complete this step, ensuring your addSubview call always occurs last.

For me, I've had to edit Unity's source code for a number of unrelated reasons, so the most natural thing was to just go directly to the line that assigns the view and comment it out. In the build output of project made with Unity version 2021.3.18f1, go to Classes/UI/UnityAppController+ViewHandling and replace the willStartWithViewController method with this.

- (void)willStartWithViewController:(UIViewController*)controller
{
    _unityView.contentScaleFactor   = UnityScreenScaleFactor([UIScreen mainScreen]);
    _unityView.autoresizingMask     = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    // original - our own superview could get replaced if set before this line runs
    // _rootController.view = _rootView = _unityView;

    // custom
    _rootView = _unityView;
}

I would make a PR for you but the Unity iOS build output is not included in this repo.

DavidPeicho commented 1 year ago

Amazing thanks. I will keep this open and try to write that somewhere, citing you. Unfortunately I do not use Unity anymore, and Swift / iOS even less

bdeweygit commented 1 year ago

After some more investigation into the problem I found a much more correct and safe solution that does not require editing Unity's code and the potential unknowns that come with messing with its view and controller hierarchies. I'll try to put together a pull request over the next couple of weeks. Solution involves putting an observer on the Unity window's root view controller as a trigger to make our subview at the proper moment and avoid the race condition, as well as react to any subsequent overrides, not that I think there are any but who knows.