cocos / cocos-engine

Cocos simplifies game creation and distribution with Cocos Creator, a free, open-source, cross-platform game engine. Empowering millions of developers to create high-performance, engaging 2D/3D games and instant web entertainment.
https://www.cocos.com/en/creator
Other
6.48k stars 1.71k forks source link

CC 3.5.1 - Scene Swap Performance is slow #11503

Open Ronsku opened 2 years ago

Ronsku commented 2 years ago

Use Case

Related to this ticket: https://github.com/cocos/cocos-engine/issues/10935

I use multiple scenes per game to keep everything organized. Just as an example, let's say you are playing a 2D overview game and walk into a door, you run a quick animation that opens the door (covering the whole screen with something) and swap scene mid animation where screen is covered by the animation. This animation could be ran on a persistent node above both scenes. This would make it possible to create a smooth transition from one scene to another.

Problem Description

Now, depending on the device you are running on the next scenes instantiation could take 100ms or 1000ms you cannot run it mid animation, instead you have to separate the animation into something

Run a "open animation" that covers the screen Wait for scene swap (100ms 1000ms or how long it takes) Then run a "close animation" to remove the overlay that covers the screen to reveal the new scene. Sometimes I've used fade to black 500ms animation, then stay at black until scene has swapped and fade back to from the black overlay in the new scene. Problem here is that I want the swap to be fast and smooth, 500ms fade to black, 500ms fade back to invisible overlay. But since it might take a long time to instantiate the next scene player might be stuck in a black screen for a few seconds wondering "what is going on..?"

Proposed Solution

This is why it would be amazing to just be able to "await preLaunch()" a scene that does all the heavy lifting and basically instantiates the scene for you in memory and when you then "launchScene()" it would be instant. The same way you would just toggle "node.active = true". And my workaround with placing a scene as persistent node solves this in an ugly way.

How it works

No response

Alternatives Considered

Make sure preloadScene() not only downloads the assets but also prepares the scene to be launched within a few milliseconds.

Additional Information

No response

Ronsku commented 1 year ago

Adding this issue here as well. I have no idea how to get to the sceneAsset without loading and applying the scene.

director.preloadScene('sceneName',
  (loaded, total) => {...},
  (err, sceneAsset) => {
    // sceneAsset is not working and always returns undefined
  }
Ronsku commented 1 year ago

Also swapping scene in the background (having current scene set as persistent node just to be able to do a fast swap) requires tons of performance. Animations start stuttering when director.loadScene() is called even though the scene loading isn't that big.

This is on a very powerful desktop machine. When throttling CPU 4x in chrome it almost freeze for a moment. I tried to empty the scene and it still is a heavy process.

What happens in the scene swap that makes it so heavy?

Zhmz commented 1 year ago

Could you provide the project to us? We try investigating the performance hotspots and give you the feedbacks.

Ronsku commented 1 year ago

@Zhmz I could make a demo, but just by dyanmically swapping scene with director.loadScene() you can directly notice that it takes some time, throttle to 4x CPU slow down and it can take even 100ms with an empty scene. Then you add just a simple image and it can bounce up to 200-300ms, add a Spine system and you have 500ms etc. It all of course depends on device performance, but if you create mobile games and want a smooth transition to next scene there is a problem.

Also when when you put your current scene as persistent and load the next scene behind the current one, you get a huge lagg spike when it instantiates, so that's no good either.

I tried this using CC 3.6.0

director.preloadScene('sceneName',
  (loaded, total) => {...},
  (err, sceneAsset) => {
    // sceneAsset is not working and always returns undefined
  }

Even though you have preloaded the scene the swap is so slow with director.loadScene(). Using director.runScene() and director.runSceneImmediate() it requires sceneAsset or Scene (name is not accepted) so need to somehow get the sceneAssets to test the performance with it as well.

How can I get the sceneAsset, when preloadScene is not returning it? Can I find it somehow in director or somewhere else? I really want to try the performance of the other ways to launch a scene.

Once you have launched a scene once and you make sure to not have the "auto release assets" checked image (so it will use a lot of memory, but rather that than very slow scene swap) Then you can swap scenes NEXT time fast, but the first time will be a slow one anyway. That's why I'm thinking that we need to somehow read it into memory ready to be used, otherwise it won't be smooth and fast?

SantyWang commented 1 year ago

The auto release asset option will affects the performance of scene switching, because when this option is checked, the assets used in the two scenes will be compared and the asset not used in the next scene will be released when the scene is switched, and this process requires traversing all properties of all persistdent nodes, so the more resident nodes there are, the higher the overhead.

SantyWang commented 1 year ago
How can I get the sceneAsset?

Could use bundle.loadScene to get scene asset.

Ronsku commented 1 year ago

Thanks, I'll give this a try again with the new CC 3.7.2!

D-Aman-S commented 1 year ago

Hey @Ronsku ,did you find a solution to this, I am facing similar issues while switching screens?

Ronsku commented 1 year ago

Hey @Ronsku ,did you find a solution to this, I am facing similar issues while switching screens?

Hi, unfortunately the only solution is to go back to the old Cocos Creator 2 version. Even through Cocos Creator 3 is better in every other way, Cocos Creator 2 smashes when it comes to initialization, instantiation and bundle size.

When Cocos Creator 3 has a matching or better engine startup time, prefab/scene instantiation time and bundle size, then it's time to move to Cocos Creator 3 and no reason I see to stay in Cocos Creator 2.

Until then we're stuck in the old version, if you need quick startup, efficient instantiation and as small bundle size as possible to get the players loaded into the games asap.

I think Cocos team is working on this, but it's probably not easy since they have 3D support in Cocos Creator 3. I just would like to be able to have a separation between 2D and 3D games, if 3D game rendering causes everything to become slower. Many of us still does only 2D games, even though the support for 3D is there.

This ticket was created over a year ago, I just have my fingers crossed. I don't want to be stuck in "legacy" projects for too long. I'm happy though to see updates now and then for Cocos Creator 2 as well 😊

SamridhChicmic commented 10 months ago

am using Cocos 3.7.3 and facing Same Issue even after the preloading of Scene director.load() taking time to Switch Scene although the its taking time in first time.hoping issue will resolve quickly..

Ronsku commented 10 months ago

am using Cocos 3.7.3 and facing Same Issue even after the preloading of Scene director.load() taking time to Switch Scene although the its taking time in first time.hoping issue will resolve quickly..

Thank you as well for testing, reporting and updating this ticket @SamridhChicmic!

@holycanvas and @Zhmz, do you have any more thoughts on this and the delay of opening a already preloaded scene. Could the preloaded scene be somehow preLaunched or read into memory, so that we could instantly swap it when needed?

lordofgame5 commented 3 months ago

Same issue here on the current latest version 3.8.3