Error that's not true

Hello, i had 1 model loaded from github, now i have 2 models loaded (to gain some space) but when the game load it give me this error


but every model works fine, this is the code for each model (the name of model and variable change of course)

// start add ship code
            var asset = new pc.Asset("Ship", "model", {
                url: "https://raw.githubusercontent.com/ayring/kallen/master/shipfinal.json"
            });
            app.assets.add(asset);
            
            app.assets.load(asset);
            var Ship = new pc.Entity(); // Create an Entity
            Ship.addComponent('model');
            Ship.model.asset = asset;
            asset.on("load", function (err, model) {
            //loaded
                Ship.model.model.meshInstances[0].material.diffuseMap=app.assets.find('wood1.jpeg','texture').resources[0];
                Ship.model.material.update();
            });
            //Ship.model.meshInstances[0].material.diffuseMap=app.assets.find('Wood.jpeg','texture').resources;
            Ship.addComponent('rigidbody', {
                type: 'static'
            });
            Ship.addComponent("collision",{
                type:"box",
                halfExtents: (0.4,2,10)
            });
            Ship.name="Ship";
            Ship.tags.add("main","sea");
            Ship.setEulerAngles(0,90,0);
            Ship.setLocalScale(35,35,35);
            Ship.enabled=false;
            // Add it to the Entity hierarchy
            app.root.addChild(Ship);
            // end add ship code

why do i get the error? how do i delete that message? Thanks.

Does it happen every time? Is it on startup?

Yes it’s at the start and not every time but most of the times

Hi @ayrin,

Can you share a project link to take a look?

Hi @Leonidas
https://playcanvas.com/editor/scene/396696 Project
https://playcanvas.com/editor/code/352037/terrain.js Script in the initialize function there is the code for import models

I think the issue is, your code not waiting for the remote asset to load, before using it.

That’s why it sometimes works and others it doesn’t, there is a rally condition there. Normally you need to wait for the ready event to fire before using that model.

Example code:

    var asset = new pc.Asset("Ship", "model", {
        url: "https://raw.githubusercontent.com/ayring/kallen/master/shipfinal.json"
    });
    app.assets.add(asset);

    asset.ready(function(){
        
        // use the asset where it's required, now the model is ready
    });

    app.assets.load(asset);

https://developer.playcanvas.com/en/api/pc.Asset.html#ready

I tryed to add it in different ways, but it gives me worst errors in the following code, seems it is very slow to load the models.

Yes, exactly, loading remote assets can be slow depending on the size of the file.

You can’t expect it to be available directly in your code to act on it. It’s important to use the ready method to make that part of your code wait before trying to do something on that model.

Additional question, the var asset is loaded inside the intialize funcion, i need to add the ready method inside another function where the Ship model is cloned how do i check if the var asset is ready or not? There isn’t a simplest way to do that? like to preload the external models?
EDIT: got another error :frowning: sigh

Rather than checking if the asset is ready or not, is possible to do whatever you need to do on the load or ready event of the asset?

Hi @yaustar yea i mean that, i’m trying to use the the ready event, is it correct if i load the asset this way var asset = new pc.Asset(“Ship”, “model”, {url:…etc…}); to check if it’s loaded in another function this way var check=app.assets.find(“Ship”); and check.ready(function(){…etc });
Thanks.

If another piece of code is waiting for the model to load, then you can fire an event. For example this.app.fire('loaded') when it is loaded, and this.app.on('loaded', function() { ... }) somewhere else to do an action upon the load.

Edit:
Another way, is to set flags, e.g. adding on @Leonidas example:

    // somewhere in init
    this.modelReady = false;

    // then
    asset.ready(function(){
        
        // use the asset where it's required, now the model is ready

        this.modelReady = true;
    }.bind(this));


    // then you can use this.modelReady flag to 
    // check if the model was loaded before using it
1 Like

Thanks @LeXXik but flags wouldn’t do coz
if (this.build[i].Ship===true) {… this will check if in the current map the ships are present or not, so if the ship is present it has to check if the 3 models are present and enable them, if not present duplicate the single model and place and enable the 3 models. So if i use the flag it will skip the whole code and will not run it. So my dubt is: the ready function is fired if the asset is loaded, i have to find the asset with app.assets.find(‘name’) the name is new pc.Asset(‘Ship’)?? Very confused about this part.

Hi @ayrin,

As a simple starting point, without getting too complex around it, can you put your code inside the ready function callback?

So you get for granted that your gameplay code will fire after your model has loaded.

Hi @Leonidas i tried to do that…here is the code, pls check lines 148 and follows and 644 and follows https://playcanvas.com/editor/code/352037/terrain.js?line=642&col=25&error=true

That’s a lot of code for a single script @ayrin! Nothing wrong with that but it makes it hard to study/maintain it.

I see you are loading two assets on top, so here is a suggestion on how to refactor this code:

initialize: function () {
    var asset = new pc.Asset("Ship", "model", {
        url: "https://raw.githubusercontent.com/ayring/kallen/master/shipfinal.json"
    });

    var asset1 = new pc.Asset("Thieves", "model", {
        url: "https://raw.githubusercontent.com/ayring/kallen/master/House01.json"
    });

    asset.ready(function(){

        asset1.ready(function(){

            // --- move your code in here, after both models are loaded and in place

        }.bind(this));        

    }.bind(this));

    app.assets.add(asset);
    app.assets.load(asset);

    app.assets.add(asset1);
    app.assets.load(asset1);
},

This code may work for 2 assets but it will not scale if you have more. For that look at Promises and especially on how to use Promise.all(), a Javascript/browser API.

:sweat_smile: I have put myself in a difficult position as always, since i was planning to add more. If i whip myself i would feel less pain :joy:

1 Like

@Leonidas btw, if you see the player code you will get crazy it’s more than 3000 lines, this is a short one :wink:

1 Like

Good time for some refactoring!

I have found this https://developer.playcanvas.com/en/api/pc.ResourceLoader.html can it be useful?