Skip to content

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

Open
@timbotimbo

Description

@timbotimbo

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    AndroidViewSurfaceBugs with hybrid composition in android.androidThis issue is specific to the Android Platform.bugThis issue refers to a bug in the pluginhelp wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions