juicycleff / flutter-unity-view-widget

Embeddable unity game engine view for Flutter. Advance demo here https://github.com/juicycleff/flutter-unity-arkit-demo
BSD 3-Clause "New" or "Revised" License
2.12k stars 514 forks source link

Lifecycle of Unity Engine #718

Open koreex opened 1 year ago

koreex commented 1 year ago

The scenario is like the following.

My app uses this widget as a model viewer. When I click an item in a model list, it opens unity widget and shows the model in unity engine. I close it and open another model. I repeat this operation several times and then I get the app crashes (on Android). I think this could be related to memory leak. So I wanted to know the correct usage of lifecycle of this widget

Thanks in advance

timbotimbo commented 1 year ago

I've got a 3D viewer in one of my apps, so this is how I approach it. I'm not saying this is the perfect approach, but it works for me.

I never kill Unity until the app is killed, to avoid the longer load times of Unity booting up. You might see a flash of the empty scene while loading, but I hide this in flutter with some UI fading.

Unity does always use some resources once it has booted, but this hasn't been an issue for me yet.

If you really want to kill Unity, you might be able to kill it using the unload function on the controller. But I haven't tested how stable this is yet. Don't use the quit function, as this will kill the entire app.

koreex commented 1 year ago

Thanks for your reply, @timbotimbo. Using two scenes can be helpful. Another question is if unity disposes of assets from the previous scene when it switches to the empty scene. There would be loaded models in the previous scene

timbotimbo commented 1 year ago

If you fully switch scenes (not additive loading), it should dispose anything that is not referenced in the new scene.

koreex commented 1 year ago

I see. Let me try. Thanks for your help @timbotimbo

hu1won commented 1 year ago

I'm working on a similar problem. @timbotimbo The method you suggested is a good method, but basically, if Unity is running, you will use resources, and then you will use all the memory, CPU, and GPU, so I don't think you will get good performance. Is there a way to completely shut down unity?

maciej-szulc commented 1 year ago

@timbotimbo Hey, how do you handle page with flutter unity widget and controller? Do you keep the widget on stack and show it when needed, or build new page with flutter unity widget and controller each time?

timbotimbo commented 1 year ago

@maciej-szulc I prefer to keep Unity in standalone pages. Like pushing a page with a UnityWidget to play a minigame, and then popping that page when the game is over.

Completely depends on your app of course, but I prefer to only use this widget when it is actually needed. Fewer chances of a hidden UnityWidget somehow crashing or slowing down the app.

maciej-szulc commented 1 year ago

@timbotimbo Thanks for the answer. I do exactly the same thing. Just wanted to clarify it with other programmers. Additionally, I use unload and dispose methods when leaving the page. Future<void> unloadAndDisposeUnity() async { await _unityWidgetController.unload(); _unityWidgetController.dispose(); }. What was unclear to me is handling UnityWidgetController. If Unity is all the time alive, it was unclear to use the controller returned in onUnityCreated. I wasn't sure if I should store UnityWidgetController as a singleton or use the one returned each time. For now ended up creating widget each time, but haven't tested everything yet.

ghost commented 1 year ago

unity empty scene use beyond 200mb RAM, it's not a small cost in simple app, so destroy unity activity is an important function. hope someone solve it.

maciej-szulc commented 1 year ago

@optemoy If you destroy it, you can't open it again. This is how embedded Unity works.

timbotimbo commented 1 year ago

The memory usage is a limitation of using Unity. Even when unloading it, it won't get much lower.

When Unity is in an unloaded state (after calling Application.Unload), it retains some amount of memory (between 80–180Mb) to be able to instantly switch back and run again in the same process. The amount of memory that’s not released largely depends on the device’s graphics resolution.

From the docs