Problems with Instantiating a Template

I’m getting an error when trying to instantiate a template but I have no idea why. The template exists and is assigned in the editor to the lobby_template attribute.

TypeError: Cannot read properties of undefined (reading ‘instantiate’)

Code:

        console.log("ATTEMPTING ASSET LOAD "+this.lobby_template.name+" NOW>>>>>>>>>>>>>>>>>>>");//Prints template name corectly
        this.lobby_template_instance = this.lobby_template.resource.instantiate();//ERROR HERE
        this.app.root.addChild(lobby_template_instance);

I cant understand why the error is happening even though the template exists and its name gets printed.

It’s saying that resource is null which means the template asset is not loaded. The asset exists which is why it can get the name, but the data (ie resource) is null because it’s not loaded.

Okay thanks, so I need to set the template to preload??..but wont that mean all its associated assets will get preloaded too …That’s exactly what I’m trying to avoid by instantiating at runtime.

You can do or load the template asset like you do with any other asset.

No, the assets aren’t connected. This also means that when you need to use the template asset, you should also load the other asset needed by the template too. Or rely on the engine doing the load when you instantiate it into the scene and each component will trigger a load on referenced assets.

Hmm, now I’m completely lost :slight_smile: I always thought the benefit of templates was that they didnt load anything in until the point I chose to instantiate them.

It looks like line 3 is missing this.?

Is there an easy way to see which objects are loading in the hierarchy at runtime. Im sure I saw something once that could show this. Without it it almost impossible to debug exactly what is and isnt loaded.

That was also true too :slight_smile: but not the main error Im trying to fix. Cheers

1 Like

Template assets are effectively a mini scene hierarchy. You can choose to have them preloaded or not. If they are not preloaded, you have to load them via code like you do with any other asset before using it.

The assets referenced in the template are separate and you can load them whenever you like (preload, via code etc).

The assets referenced in the template aren’t ‘connected’ to the template asset. Loading the template asset will not load any assets it references. And inversely, unloading the template asset will not unload the assets used by the template.

Separate from that, when referenced assets is used in the scene (eg a render asset by a render component) but the asset is not loaded, On the first time it is attempted to be used, it will trigger a load of the asset and won’t render until the asset is loaded.

This means that if you instantiate a template into the scene and the assets it uses aren’t loaded yet, it will attempt to load them and they will render in the scene as each asset is loaded.

You can see which files are being loaded via the network tab in browser devtools. That’s about as close as you will get to this right now.

Okay Thanks. Looks like I need to focus more on

this.app.assets.load(this.myAsset);

than templates I think. Cheers

To fix this immediate issue you having, the code would be something like this:

this.lobby_template.ready((asset) => {
    this.lobby_template_instance = asset.resource.instantiate();
    this.app.root.addChild(lobby_template_instance);
});
this.app.assets.load(this.lobby_template);

We add a callback to the asset when it is loaded which creates an instance of the template and adds it to the scene.

Then we tell the engine to load the template asset.

Documentation around assets preloading and streaming: Preloading and Streaming | Learn PlayCanvas

2 Likes

Thanks, the problem here is that I instantiate the template once the template is loaded, but none of the resources for the template are yet loaded.

How do I instantiate the template only once everything is ready to be displayed?

You have to load the assets that are used by the template and wait for them to be fully loaded before instantiating the template.

I normally tag all the assets used by the template and then use this.assets.findByTag (AssetRegistry | PlayCanvas API Reference) to get all the assets to load.