Selecting a template to preload

Hi everyone !

I’m working on a new product configurator, with a lot of models (templates?). It’s a bit long to load and I have a least twice the amount of models to add in the configurator.
It’s linked to an ecommerce, and what I’ve done is the following :

  1. Disable and uncheck the preload bools on all the assets.

  2. Get the product reference (from the ecommerce) and set the URL of my playcanvas iframe with a GET parameter, like this : https://playcanv.as/e/p/ZNI9rek9/?ref=1ATHFUP ( You can try it, it’s a real link :stuck_out_tongue: )

  3. Enable the product I want like this :

        var sParamstring = window.location.search;
        var sParams = new URLSearchParams(sParamstring);
        var ref = sParams.get('ref');
        var myAsset = pc.Application.getApplication().root.findByName(ref);
        if (template) template.enabled = true;

This happens in the start event callback of the app, before the hideSplash function.

It works OK but it’s still a bit long to load and the splash screen is hidden before the whole template is loaded.

I also tried to hide the splash screen later, like this :

       var vetAsset = app.assets.list().filter(e => e.type == "template" && e.name == ref)[0];
       app.on("load:" + vetAsset.id, function(){
           hideSplash();
       });

But this doesn’t work, the event isn’t fired.

Not sure what I’m doing wrong exactly, and it doesn’t feel like the proper way to do this :sweat_smile:
So my question is : How can I preload only the template I need?

Thanks in advance for the help!

I can’t see in the code you have posted here where you are actually calling the function to load the asset?

Hi yaustar, thanks for the reply.

I used this template.enabled = true to trigger the loading. It loads the template with all the render components inside it (I’m having trouble with all the different types. Models, templates, renders… :smiley: )

Should I use app.assets.load(vetAsset); instead?

The approach I would take is to tag all the models, textures, etc assets that are needed for the template and the template asset with the same tag (eg 1ATHFUP )

Then you can get all the assets by tag and load them.

Example project on how to do that here: Load multiple assets at runtime | Learn PlayCanvas

Once all the assets have loaded, you can hide the splash.

Hi again :slight_smile:
I think I’m mixing things in my head and I might be a bit lost between templates, models, instances of templates etc…

Right now in my project, I have all my FBX files that have been automatically converted from FBX to GBL and then an Template object is created.
I take that Template, drag and drop it in my tree, and that makes an instance.

And now this is where I do something wrong I guess :

With pc.app.assets.find I can find the template, load it in the AssetRegistry with pc.app.assets.load(myAsset)
But that doesn’t show me my model, as it’s not in my scene (I guess?)

With pc.app.root.find I can find the instance of my template, and enable/disable it in order to show or hide it. But I looks like this instance was already loaded, and I see no preload option for this instance (That sounds logic after all, it’s an instance :stuck_out_tongue: )

Soooo, after all this potential nonsense, depending on my understanding or not…
Should I remove all my instances from my root tree, and do this at runtime :

  1. Find my template with pc.app.asset.find (by name or tag)
  2. Load it in the asset registry
  3. instanciate it
  4. Add it to the root tree
  5. Enjoy?

Something like this :

var myTemplate = pc.app.assets.find("1MINUP", "template");

myTemplate.ready(function() {
  var myInstance = myTemplate.resource.instantiate();
  pc.app.root.addChild(myInstance);
  myInstance.enabled = true;

  console.log("Enjoy!");
});
pc.app.assets.load(myTemplate);

Is this the way? :mortar_board:

I’m a little confused here.

If you have an instance of the template in the hierarchy in the Editor, that instance is ‘baked’ into the scene and has no connection to the Template asset at runtime. Whether the template asset is unloaded/loaded at runtime, makes no difference to the instance in the scene.

Template assets only needed to be loaded at runtime if you need to instantiate them at runtime.

Hehe the confusion comes from my global confusion I guess !

My knife configurator has only a few different lightweight models, so I have everything already in the hierarchy and I had no big loading problems.
This time my project has a lot of models (60+), and they all weight between 30 and 120mb.
With the new template system, I did the same and I had put all the generated templates in my hierarchy.

So if I understand it well, if something is in the hierarchy, it will be always loaded at runtime (and losing the link with the asset)?

I’ve removed everything from the hierarchy and I select&instanciate a template asset at runtime, and it seems to load rather OK for a first try : example product

Yes. Not sure if ‘losing’ is the correct term but yes, the concept is correct.

As long as the template assets (including the models, textures, etcs) are not set to preload and you load them all at runtime, you should be good :slight_smile:

1 Like

Me again :smiley:

It’s working mostly OK but I still have a noticeable loading time between the “ready” event of my template, and the included entities appearing on screen. ( testable here )

I hide my splash screen when the template is loaded, and the models appears only later.
I’ve written a bit of code (see below) to see when the entities are loaded, but I still have to wait more before everything appears even if everything seems loaded (materials and textures are preloaded).

loading

pc.app.assets.load(myTemplate);

var onAssetLoaded = function (asset) {
    console.log(`${asset.name} is loaded !`);
};

if (Object.keys(myTemplate.data).length > 0) {
    var entities = Object.values(myTemplate.data.entities);
    entities.forEach(entity => {
        if (Object.values(entity.components).length > 0) {
            var assetId = entity.components.render.asset;
            var asset = pc.app.assets.get(assetId);
            asset.ready(onAssetLoaded);
        }
    });
}

How can I find what is making my model appear late? Is it really loading something?
The fact that all the entities trigger their ready event at the same time makes me think that I messed up something and that they aren’t really “ready” yet…

Also, Template.data.entities do not exist anymore once the project is build. How can I find all the entities linked by a template? I’ve seen this tutorial but I have hundreds of models, I don’t want to have to tag them all (will do if I really need too though…).

ps: My templates all look like this :
image

Thanks in advance for the help :smiley:

That’s private API so what’s there is not guaranteed.

Use the network tab and disable caching in the browser devtools to see what is actually being downloaded.

I would still go by the tagging assets approach mentioned before: Selecting a template to preload - #4 by yaustar

Render assets are just indexes to a set of meshinstances in the GLB container. If the GLB is not loaded when the render asset needs it, it kicks off a load of the GLB container asset. This is probably what is causing the delay.

Easy way to test it is to set the GLB container as preload and see if you still running into the same issue

Thanks for your reply :slight_smile:

Whoops, understood haha, I tend to play around too much and should stick more to what’s explained in the documentation :stuck_out_tongue:

Thanks! Also a good way to find unwanted preloaded assets!

That does the trick, and also it’s nice because the loading of this GLB is included in the progress bar progress. I can’t preload all the GLB’s because there are too many and they are too big (the size is another problem, the person making these models is working on it).
Is there maybe a way of adding an asset to the list of assets to preload, at runtime?

For now, I can find the associated GLB as it has the same name as my template. And it seems that only loading this particular GLB is enough for what I need. I just have to show a message on the splash screen and change the progress bar for a spinner while the GLB loads :slight_smile:
Example here

Thanks for the help !

As that fixes the issue, I would tag all assets needed for the template with the same tag, take the GLBs off preload and find all assets by tag and load them via that method (which is what I would do).

The render asset has private API that has the asset id to the GLB container if you want to risk that. The process would be to load the render assets than load the GLB container from that

1 Like