DavidPeicho / unity-swiftui-example

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

Compose Unity into SwiftUI whenever internal superview is changed #14

Open bdeweygit opened 1 year ago

bdeweygit commented 1 year ago

Closes #13

These changes are for the old/unity2020 branch. The code in the main branch does not actually compose Unity into a SwiftUI element and so is not applicable to this problem/solution.

Creating a SwiftUI element that displays Unity was already accomplished by way of the container view technique; a custom UIViewControllerRepresentable sets Unity's internal root view as its subview. However, this is not guaranteed to always work because we don't know when and if Unity will make its root view a subview of something else internally. This is indeed the case shortly after running Unity, and it resulted in our superview getting replaced and Unity not showing.

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.

In effect we have a race condition between who can apply their superview last, our code or Unity's code. We solve this problem by recognizing the fact that Unity's root view belongs to its root view controller which in turn belongs to its UIWindow. The window takes the role of a superview. Therefore, the superview-subview hierarchy is only established when the rootViewController property of the window is set (or reset). By registering an observer on this property, we can apply our superview immediately after the hierarchy is complete. This ensures our desired hierarchy always takes precedence and is maintained for the duration of Unity's lifecycle.

It is also worth mentioning that as a true SwiftUI element, we can resize and reposition Unity as we see fit. Unity's own documentation says

Unity as a Library only supports full-screen rendering, and doesn’t support rendering on part of the screen.

which is true by default, but we have bypassed this with the container view technique. We demonstrate this with the example element OtherUnityView.

bdeweygit commented 1 year ago

@DavidPeicho I think I'm done making commits; it runs without error. Please review at your leisure.

bdeweygit commented 1 year ago

I was just reading through issue #3 and I do see on higher versions of Unity that same problem. The code here works fine on version 2020.2.1f1 for which this branch was made, but I will see if I can address that problem on 2021.3.18f1 which is the version I am using in my own project.

bdeweygit commented 1 year ago

It now works correctly on both 2020.2.1f1 and 021.3.18f1 - we can interact with our own content as well as the content within Unity itself, so the problems described in #3 are gone. I added your AutoRotate.cs script to demonstrate touch interaction with the Unity view; up to you if you want to add the color picker thing as well and/or upgrade the Unity version. At this point I'm not sure what advantage if any the main branch has over this code since the solution here is more succinct and more powerful in terms of UI. Let me know what you think.

Phantom-Addy commented 1 year ago

@bdeweygit Thank you so much for forking the project! It works perfectly and even solves issues #10 #9! Really appreciate it!