flutter-unity-view-widget icon indicating copy to clipboard operation
flutter-unity-view-widget copied to clipboard

UnityView initial size wrong on iOS

Open WouterVandenputte opened this issue 3 years ago • 6 comments

Describe the bug Unity view takes whole screen while it shouldn't

I Have a UnityView with a banner below it. On Android, my code works flawlessly but on iOS it has some weird behaviour: the banner is on top of the unity view instead of directly below it.

The code is below.

return Column(
      mainAxisSize: MainAxisSize.max,
      children: [
        Expanded(
          child: UnityWidget(
            borderRadius: BorderRadius.zero,
            onUnityCreated: _onUnityCreated,
            onUnityMessage: _onUnityMessage,
            onUnitySceneLoaded: _onSceneLoaded,
          ),
        ),
        Container(width: banner.size.width.toDouble(), height: banner.size.height.toDouble(), child: AdWidget(ad: banner))
      ],
    );

HOWEVER! There's a button in another widget which has a callback that does a setState.

 setState(() {
       someVariable= someValue;
 });

and pressing this button does fix it (it makes the unity view resize to its available size (i.e. withouth taking the size for the banner as well)). I already tried a 'hack' by calling set state after a second but this doesn't solve the problem unfortunately. I must also say that the splash screen does not show up on iOS, while it does show on Android.

Expected behavior iOS behaviour identical to Android Expanded(child: UnityWidget(...)) takes exactly the size that Expanded promises it should take (maximum available)

Unity (please complete the following information):

  • OS: Windows
  • Version 2021.2.5f1

Smartphone (please complete the following information):

  • Device: iPhone 8
  • OS: iOS 14.8.1

Additional context Only occurs on iOS, not on Android.

WouterVandenputte avatar Dec 30 '21 20:12 WouterVandenputte

With the latest release (4.2.3), I can reproduce the same behaviour both in the demo and in my project.

On Android, everything looks great. On iOS, the rendered Unity image size is too big.

I've found it's possible to force fix the image size by pausing then resuming the UnityWidgetController once the plugin has initialized:

void _onUnityCreated(UnityWidgetController controller) {

    // iOS hack: Force Unity integration to redraw the view.
    if (Platform.isIOS) {
      controller.pause();
      controller.resume();
    }
  }

The force fix doesn't appear to work in Column / Row widgets however. For now, I've had to place my UnityWidget underneath full-screen in a Stack, and overlay my other Row/Column UI on top of the UnityWidget.

Hope this helps!

russelljahn avatar Dec 31 '21 20:12 russelljahn

Thanks for the info Unfortunately I cannot work with a stack, this would obscure the UntiyWidget. Do you perhaps know if this is specific to 4.2.3? If not, I could perhaps just take an earlier version

WouterVandenputte avatar Jan 01 '22 19:01 WouterVandenputte

I have refactored the app a bit such that no columns/rows are used. This is how I have it now

Widget build(BuildContext context) {
    return SafeArea(
      top: true,
      bottom: true,
      child: Scaffold(
        body: Stack(
          children: [
            UnityWidget(
              borderRadius: BorderRadius.zero,
              onUnityCreated: _onUnityCreated,
              onUnityMessage: _onUnityMessage,
              onUnitySceneLoaded: _onSceneLoaded,
            ),
          ],
        ),
      ),
    );
  }

  void _onUnityCreated(UnityWidgetController controller) {
     print('Unity view created');
    _controller = controller;

    _handleIphoneBug(controller);
  }

  Future<void> _handleIphoneBug(UnityWidgetController controller) async {
    if (Platform.isIOS) {
      print('pausing and resuming controller');
      await controller.pause();
      await controller.resume();

      await Future.delayed(const Duration(seconds: 10));
      print('pausing and resuming controller again after 10 seconds');
      controller.pause();
      controller.resume();
    }
  }

But the result is exactly the same. I tried both by simply calling and awaiting pause and resume and by calling them without awaiting it after a while. Unfortunately :(

WouterVandenputte avatar Jan 09 '22 18:01 WouterVandenputte

Same problem here :( does anyone found a solution to this ? It does not work even with a Stack for me, fullscreen enabled or not.

Ortes avatar Feb 22 '22 08:02 Ortes

I found a workaround by using a FutureBuilder with some delays (e.g. 2s). The UnityWidget will work with the correct size.

wtong2017 avatar Mar 03 '22 14:03 wtong2017

I have fixed it with a scaffold key, the first time it initializes:

void _onUnityCreated(controller) {
   if (controller.unityId == 1) {
       _scaffoldKey = GlobalKey<ScaffoldState>();
    }
}
Scaffold(
          key: _scaffoldKey

romanalfaro avatar Mar 22 '22 07:03 romanalfaro