Skip to content

[AndroidViewSurface] On app resume, a hidden UnityWidget renders on top of other widgets. #647

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

Open
timbotimbo opened this issue Jul 6, 2022 · 9 comments
Labels
android This issue is specific to the Android Platform. AndroidViewSurface Bugs with hybrid composition in android. bug This issue refers to a bug in the plugin help wanted Extra attention is needed

Comments

@timbotimbo
Copy link
Collaborator

timbotimbo commented Jul 6, 2022

Describe the bug
This is a bug that occurs when a UnityWidget is kept alive in the widget tree, but hidden by another widget.
In the following example the UnityWidget is in a Pageview, where it can be hidden by another page.
When you leave the app and return it from the background, the UnityWidget renders on top of the visible page, and does not detect touch input.

This only happens in Hybrid composition mode, which is enabled with useAndroidViewSurface: true.

To Reproduce
Steps to reproduce the behavior:

  1. Paste the example code in the main.dart file of the example project.
  2. Make sure there is an export in android/unityLibrary
  3. Switch between the pageview tabs to get unity to launch.
  4. Move the app to the background with the Unity tab not selected.
  5. Return to the app, you should see a red page, but Unity will be visible on top of it.
    Unity does not respond to touch events until you switch to the unity page again.

Expected behavior
The Platformview is only shown when the UnityWidget is visible in the widget tree. In the example only on the blue page.

Video

Screen_Recording_20220706-125630.mp4

Code sample
Paste the following code in main.dart of the flutter_unity_widget example project.

code to reproduce the issue
import 'package:flutter/material.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;

  PageController pageController = PageController(initialPage: 0);

  void bottomTapped(int index) {
    setState(() {
      _selectedIndex = index;
      pageController.jumpToPage(_selectedIndex);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: PageView(
        physics: NeverScrollableScrollPhysics(),
        controller: pageController,
        children: <Widget>[
          Red(),
          Unity(),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: (index) {
          bottomTapped(index);
        },
        items: [
          BottomNavigationBarItem(
            icon: new Icon(Icons.home),
            label: 'Red',
          ),
          BottomNavigationBarItem(
            icon: new Icon(Icons.gamepad_outlined),
            label: 'unity',
          ),
        ],
      ),
    );
  }
}

class Red extends StatefulWidget {
  @override
  _RedState createState() => _RedState();
}

class _RedState extends State<Red> {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
    );
  }
}

class Unity extends StatefulWidget {
  @override
  _UnityState createState() => _UnityState();
}

class _UnityState extends State<Unity> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;
  UnityWidgetController _unityWidgetController;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    _unityWidgetController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Container(
      padding: EdgeInsets.all(50),
      color: Colors.blue,
      child: UnityWidget(
        onUnityCreated: _onUnityCreated,
        onUnityMessage: onUnityMessage,
        onUnitySceneLoaded: onUnitySceneLoaded,
        webUrl: 'http://localhost:6080',
        useAndroidViewSurface: true,
      ),
    );
  }

  void onUnityMessage(message) {}

  void onUnitySceneLoaded(SceneLoaded scene) {}

  void _onUnityCreated(controller) {
    controller.resume();
    this._unityWidgetController = controller;
  }
}

Versions

  • Unity 2022.1.7f1
  • Flutter 3.0.3
  • fuw: 2022.1.1+4
  • unitypackage: fuw-2022.1.1-v2.unitypackage
  • Android 12 (maybe others too)

[UPDATE]
Still a problem with:

  • Flutter 3.7.0
  • fuw 2022.2.0
@timbotimbo
Copy link
Collaborator Author

After testing on fuw 2022.1.0+7 and Flutter 2.10.5, it seems to be surfaceView related.
With flutter 2.10.5 the issue only occurs with useAndroidViewSurface: true, setting it to false makes it behave like it should.

Flutter 3 compatible versions require using androidViewSurface, therefore this is a regression in versions 2022.1.1+x.

@timbotimbo timbotimbo changed the title [Android] On app resume, a hidden UnityWidget renders on top of other widgets. [AndroidViewSurface] On app resume, a hidden UnityWidget renders on top of other widgets. Jul 6, 2022
@dawiddszewczyk dawiddszewczyk added Build This issue refers to the build configuration and builds failing. help wanted Extra attention is needed labels Jul 17, 2022
@dawiddszewczyk
Copy link
Collaborator

@juicycleff Can you look on that issue?

@Ahmadre
Copy link
Collaborator

Ahmadre commented Jul 17, 2022

Describe the bug This is a bug that occurs when a UnityWidget is kept alive in the widget tree, but hidden by another widget. In the following example the UnityWidget is in a Pageview, where it can be hidden by another page. When you leave the app and return it from the background, the UnityWidget renders on top of the visible page, and does not detect touch input.

To Reproduce Steps to reproduce the behavior:

  1. Paste the example code in the main.dart file of the example project.
  2. Make sure there is an export in android/unityLibrary
  3. Switch between the pageview tabs to get unity to launch.
  4. Move the app to the background with the Unity tab not selected.
  5. Return to the app, you should see a red page, but Unity will be visible on top of it.
    Unity does not respond to touch events until you switch to the unity page again.

Expected behavior The Platformview is only shown when the UnityWidget is visible in the widget tree. In the example only on the blue page.

Video

Screen_Recording_20220706-125630.mp4
Code sample Paste the following code in main.dart of the flutter_unity_widget example project.

code to reproduce the issue
Versions

  • Unity 2022.1.7f1
  • Flutter 3.0.3
  • fuw: 2022.1.1+4
  • unitypackage: fuw-2022.1.1-v2.unitypackage
  • Android 12 (maybe others too)

does this also happen on Flutter Stable 3.0.5?

@hidfsobg
Copy link

hidfsobg commented Jul 18, 2022

@Ahmadre yes,it also happened on Flutter Stable 3.0.5. I donot kown how to fix it. @juicycleff Can you look on that issue?

@Ahmadre
Copy link
Collaborator

Ahmadre commented Jul 25, 2022

@Ahmadre yes,it also happened on Flutter Stable 3.0.5. I donot kown how to fix it. @juicycleff Can you look on that issue?

Did you try:

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  switch (state) {
    case AppLifecycleState.resumed:
      unityWidgetController.resume();
      break;
    case AppLifecycleState.paused:
      unityWidgetController.pause();
      break;
    default:
  }
}

For more read Flutter's: WidgetsBindingObserver

@juicycleff
Copy link
Owner

Seems like a Flutter 3.0.0 issue taking a look

@timbotimbo
Copy link
Collaborator Author

It doesn't seem related to Flutter 3.

In Flutter 2.10.5 the bug only happens with useAndroidViewSurface: true,
In Flutter 3.0.0 - 3.0.5 it always happens because useAndroidViewSurface is forced.

In Flutter 3.3.0-0.0.pre the bug only happens with useAndroidViewSurface: true.
(I uncommented the Flutter 3 AndroidView section in device_method.dart to get the classic platformview back with useAndroidViewSurface: false)

@invisible-defects
Copy link

Still able to reproduce the issue. Unity's new input system doesn't seem to work with useAndroidViewSurface: true because of this bug.

@timbotimbo timbotimbo added bug This issue refers to a bug in the plugin android This issue is specific to the Android Platform. and removed Build This issue refers to the build configuration and builds failing. labels Jan 8, 2023
@timbotimbo timbotimbo added the AndroidViewSurface Bugs with hybrid composition in android. label Jan 24, 2023
@timbotimbo
Copy link
Collaborator Author

Just tried it again in Flutter 3.7.0 on Android 13.
It seems to have gotten a little worse.

screen_recording.mp4

I found this Hybrid composition issue in the Flutter repo that seems like the same problem. flutter/flutter#89558

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android This issue is specific to the Android Platform. AndroidViewSurface Bugs with hybrid composition in android. bug This issue refers to a bug in the plugin help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

6 participants