Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: refactored unity controller to a global singleton #733

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

juicycleff
Copy link
Owner

@juicycleff juicycleff commented Dec 16, 2022

Description

Many times we want to control unity without having UnityWidget in the screen or during route transition load a unity scene. Both of these cases was impossible because the unity controller lives as long as the activie unitywidget is mounted.

This PR introduces a singleton flutter unity controller that lives outside the life span of the widget. That is you can control your unity instance from anywhere in your flutter code.

API spec

Listen to stream anywhere

FlutterUnityController.instance.onUnityMessage().listen((event) {
      // handleMessage(event.value);
});

Filter events by type to stream anywhere

FlutterUnityController.instance.stream.listen((event) {
      if (event.eventType == UnityEventTypes.OnUnityViewCreated) {
          // handleMessage(event.value);
      }
});

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

@juicycleff juicycleff changed the title refactor: refactored unity controller to a global singleton that live… refactor: refactored unity controller to a global singleton Dec 21, 2022
@juicycleff juicycleff marked this pull request as ready for review December 30, 2022 05:23
@timbotimbo
Copy link
Collaborator

timbotimbo commented Dec 30, 2022

I just did a check on android and here is my first impression, I will do more testing and try iOS later.

It doesn't seem to be a breaking change for the existing example project, but the singleton needs some adjustments or documentation, as it doesn't always work as I would expect.

The biggest issue is the last bullet point, crashing with unload.

Using FlutterUnityController before a UnityWidget is used:

  • create returns null and doesn't do anything. I would expect it to start a hidden Unity instance.
  • Most other functions return without any result or error (pause, resume, quit, unload, init).
    If this is intended, maybe print a warning or error about initializing the controller first.
  • isLoaded isReady isPaused return false as expected.
    InBackground throws an exception:
MissingPluginException (MissingPluginException(No implementation found for method unity#inBackground on channel plugin.xraph.com/base_channel))
  • postMessage with setRotationSpeed gets me a nice error.
    Native libraries not loaded - dropping message for Cube.SetRotationSpeed
  • openInNativeProcess works as expected and starts a new standalone unity instance.

Using FlutterUnityController without a UnityWidget, after disposing a UnityWidget:

  • postMessage, openInNativeProcess and quit work as expected.
  • create, pause and resume dont really seem to do anything.
  • isLoaded isReady isPaused all return true. But i'm not sure if it is actually paused.
  • unload will crash the app on the next UnityWidget. Even if I call create or init before opening the UnityWidget.
call to OpenGL ES API with no current context (logged once per thread)

EDIT:
This branch has some updates to the example that I used to play around with the controller. Not final enough for a pull request, but it might be helpful.

@timbotimbo
Copy link
Collaborator

timbotimbo commented Dec 31, 2022

WebGL is an interesting one. Unity doesn't stay active without a UnityWidget and boots from the splash screen for each UnityWidget. This makes the new streams kind of useless as we need to have a UnityWidget open anyway.

The current api_screen.dart example is now broken on web as FlutterUnityController.instance throws errors where _unityController doesn't. (error is from FlutterUnityController.instance.postMessage)

MissingPluginException(No implementation found for method unity#postMessage on channel plugin.xraph.com/base_channel)

I'm not sure it is worth the effort to implement the new method channels on web if they don't add new functionality. But it would be nice to fall back to the existing controller to avoid breaking things.

@juicycleff
Copy link
Owner Author

WebGL is an interesting one. Unity doesn't stay active without a UnityWidget and boots from the splash screen for each UnityWidget. This makes the new streams kind of useless as we need to have a UnityWidget open anyway.

The current api_screen.dart example is now broken on web as FlutterUnityController.instance throws errors where _unityController doesn't. (error is from FlutterUnityController.instance.postMessage)

MissingPluginException(No implementation found for method unity#postMessage on channel plugin.xraph.com/base_channel)

I'm not sure it is worth the effort to implement the new method channels on web if they don't add new functionality. But it would be nice to fall back to the existing controller to avoid breaking things.

Yeah it's only for mobile and nor for web. Web can still keep using unity widget controller

@jesseburstrom

This comment was marked as off-topic.

@timbotimbo
Copy link
Collaborator

timbotimbo commented Jan 7, 2023

@juicycleff
I ran into some regressions on iOS.

1

White screen when returning to UnityWidget:

  • Run example project
  • Open No interaction Unity demo
  • Press Switch Flutter Sceen
  • Press back button

Now the no interaction demo page shows only white, instead of Unity.
This works fine on master, but is broken in this branch.
(Found on iPad with iPadOS 16.1, and Running on Mac mini m1 “Designed for iPhone”)

2

Might be the same issue, but I did not see this on the iPad, only on the Mac in “Designed for iPhone“ mode.

  • Run the example project
  • Open any of the demo pages
  • The page is white and Unity does not show up.
  • Closing the page and opening any page a second time fixes it.

This only happens on Unity's first boot. Once you've got it visible it will keep working.
Works fine on master branch, bug is introduced in this branch.
This one seems like #540 (fixed in #595) is reintroduced here.

@kamami

This comment was marked as off-topic.

@timbotimbo

This comment was marked as off-topic.

@juicycleff
Copy link
Owner Author

@timbotimbo sorry for being MIA for so long. Life happened, I will try to give the PR a lift and see where thing things lead.

@timbotimbo
Copy link
Collaborator

@juicycleff Welcome back. Can you look into publishing a plugin update before merging this?

There have been quite a few bug fixes since 2022.2 and I think it is a good idea to have a 'safe' version before a major change like this.

Some fixes have been merged in master, but there are a few open pull request that still need a look too.

@juicycleff
Copy link
Owner Author

Hey @timbotimbo sure I'm currently looking at everything and will make a release as soon as I'm done probably tonight

@Velek
Copy link

Velek commented Jan 2, 2024

I have been thinking this would be nice to have so I can make it accessible with Provider.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants