iOS and visionOS: App crashes at startup with the message "[UnityViewControllerBase getInstance]: unrecognized selector sent to class...".

Symptoms

  • The application crashes at startup with the exception message "[UnityViewControllerBase getInstance]: unrecognized selector sent to class...".
  • The project contains other native graphics plugins, like Vuforia.

Cause

Unity's low-level rendering plugin system for iOS and visionOS has a design flaw that causes rendering plugins to clash with each other, but 3D WebView is designed to work around this with a few tweaks.

Resolution

Unity's low-level rendering plugin system for iOS and visionOS is designed such that a plugin must create a subclass of the UnityAppController Objective-C class and then register itself as the application's app controller using Unity's native IMPL_APP_CONTROLLER_SUBCLASS() macro. A limitation to this design is that an application can have only one app controller, so if multiple rendering plugins take this approach, only one will ultimately be used. A workaround for this design flaw is to modify the app controller for one plugin to make it so that that it subclasses the app controller for another plugin. This allows the subclass to contain the logic for both plugins' app controllers, so registering the combined app controller allows both plugins to function correctly. To facilitate this workaround, 3D WebView for iOS includes the source code for its app controller in the VXWebViewAppController.h and .mm files.

Directions for Vuforia

Vuforia is the most popular rendering plugin for iOS, and due to the limitation described above, it clashes with 3D WebView when they are included in the same project. To resolve this issue, you can instead use the following version of the VXWebViewAppController.h, which is modified to extend Vuforia's app controller. When you build for iOS, Unity automatically includes a VuforiaNativeRendererController.mm file which also needs to be modified so that its call to IMPL_APP_CONTROLLER_SUBCLASS(VuforiaNativeRendererController) is commented out. The following copy of VuforiaNativeRendererController.mm is modified to illustrate that change that needs to be made:

General directions

  1. If your project isn't using Vuforia, the first step is to determine what other plugin in your project is clashing with 3D WebView. One option is to search your repo for the macro IMPL_APP_CONTROLLER_SUBCLASS. If you find another plugin that uses that macro, then you can proceed to step 2. If you don't find another plugin, it could be because its code that uses IMPL_APP_CONTROLLER_SUBCLASS() is provided as a compiled library instead of provided as source. In that case, you could gradually remove plugins from your project to locate the clashing plugin through process of elimination. If you locate the clashing plugin and find that it is provided as a compiled library instead of as source, you may need to contact the library's author to ask how you can access its embedded app controller and prevent it from registering itself as the application's app controller.

  2. Once you have located the other rendering plugin's app controller, you can make the following modifications:

    a. Modify the other plugin so that it doesn't register its app controller as the one the application should use (i.e. comment out its line of code that calls IMPL_APP_CONTROLLER_SUBCLASS()).

    b. Modify VXWebViewAppController.h so that it subclasses the other plugin's app controller instead of UnityAppController.

For an example of this approach, please see the Vuforia files that are linked to in the section above.