Performance issue with large scene


#1

Our team is working on a game of which the ui is kind of complicated and takes more than 1500 entities.

When run on a modern smart phone (4GB RAM, snapdragon 660), it takes 2 seconds to create the scene, and more than 7 seconds on an older phone (presented in 2014, 3GB RAM, snapdragon 801).

Any suggestion about how to speed this up would be well appreciated.


#2

Hmm 2014 isn’t so old!

I think your best option is to uncheck “PreLoad” from all assets so the game loads instantly and just goes importing all of the assets in runtime.

Other than that, revise texture sizes, models etc and optimize them for a quicker load.


#3

I would start with benchmarking first to see where the bottle necks are.

Are they from network loads?
Logic being performed in the initialize functions?
Simply from having 1500 empty entities?

Other ideas include staging the initialisation of the scene over several frames. Do they all need to be active/there at the start? Can you use some form of spatial partitions to load areas of the scene only when they are in use/visible?

Edit: just read it’s just purely from the UI. 1500 sounds a lot and I can’t imagine any UI that needs that many. (Nor have I come across one that requires that many)

Like I mentioned above, does it all need to be created at once at the beginning? Is it all shown at once? Can you create it over several frames? Where’s the bottles necks shown in the profiler? Can the number of entities used be reduced in the UI?


#4

The UI is created with the online playcanvas editor then exported to a web bundle. This produces a config.json and one json file per scene. During run time, the scene is loaded with pc.Application.loadSceneHierarchy.

Although most of the UI entities are hidden at the start, pc.Application.loadSceneHeirarchy creates them no matter enabled or not.

We modified the engine code to find more details, and now we know:

  1. loading and parsing the scene json file takes around 1.5 seconds (the json file is 1.6MB ToT);
  2. creating entities and components takes around 3.5 seconds;
  3. component initialization takes around 1.5 seconds;

Above data is from and older phone (presented 2014, 3GB RAM, Snapdragon 801).

The problem is recreating the UI without playcanvas editor would take a lot time, so we really want a better approach to solve this.

EDIT: We’re now trying to reduce the entities used


#5

You can split the UI into multiple scenes and load them additively over a series of frames to reduce the initial load. That would be the bandaid solution.

Beyond that, 1500 entities just sounds insane for a UI without context of what it is.

Edit: I assume that 1500 is for several UI screens worth? In which case, I would split up the screens (or groups of screens) into separate scenes and load them only when needed to balance out the load.


#6

thanks for the help.

you are right, this is the home scene for our game. so we added all pop-up window (might be used more than once) to the home scene. this used to be done with prefab in other game engine.

this is our very first project, we have been working on this for more than one year. due to lack of experience, we didn’t notice it until now, it became a bottleneck of our game.
not sure how you guys deal with prefab-like features. maybe “loadSceneHeirarchy” could have a “preload” feature too? so it could load invisible entities in the background? that might involves script binding though.


#7

and after some research, we found based on the project size, splitting the UI now involves tremendous work and uncertainty. we sincerely hope there is some ways to load entities in a non-blocking way…


#8

The closest you can get to prefabs in PlayCanvas is to use the clone function on entities. Typically, the pattern is to have a disabled entity (e.g an item entry) and clone it when needed and return it to a pool instead of destroying it.

I can’t think of any other way to do this without splitting it into scenes as PlayCanvas is single threaded.

You might be able to patch the engine and add an asynchronous load hierarchy function using a webworker so at least you can have an animated loading scene?


#9

I don’t see any solution with webworker due to the structured clone algorithm limitation.

I’ll dig deeper into the hierarchy handler.


#10

Might be worth just deleting all the hidden UI elements (in a forked project) and see if that makes any significant different to the load. This should give some information on how far down the rabbit hole you will need to go.


#11

this was tested first, we deleted half of the entities and the load time improved 1/3.
that’s why we are trying hard to find a solution…


#12

Looks like you will need to write your own scene loader that can only create X number of entities per frame. Looking at the engine code, it doesn’t look too difficult to do. Most of the work is on the scene parser here: https://github.com/playcanvas/engine/blob/7f84f62cf797585c62f70f904d9cd475b02775da/src/resources/parser/scene.js


#13

You can inspect (profile code, see networking time etc.) it via USB debugging + Chrome remote connection.


#14

Thanks alot for your reply @yaustar!

Although we can create entities and components in several frames, the scripts must be initialised after all other work done. Because scripts depends on entities and other components to work correctly.

So the best result we can get is something like a progeess bar during scene creation.

Is that correct?


#15

That’s what I’m envisioning, yes. The initialize and postInitalize are most likely to have to be done on a single frame but the creation of the entities should be doable over several. I had a crack at it last night but got stuck with the editor only code of loading scenes. If I get time, I will have another shot at it later.