[SOLVED] Need to unload a loaded glb-model

I load an external glb by:

self.entity.addComponent('model', {
            asset: asset.resource.model
        });

And then I want to unload it (in order to reset it)

LoadExtGlbFullOwnTexture.prototype.unloadModel = function(){
    var app = this.app;
    var self = this;
    self.entity.destroy('model'); // or self.entity.destroy();
          
};

Output from both: Uncaught TypeError: Cannot read property ‘script’ of null

By unloading you mean to remove it from VRAM right? For any asset you can do it like this:

asset.unload();

To remove the model component the right syntax is this:

self.entity.removeComponent("model");

Check the pc.Entity class on the docs for more:

https://developer.playcanvas.com/en/api/pc.Entity.html#removeComponent

1 Like

nice … VRAM, is not that important, as I want to reload the exact same model (I hope the browser/OS recognizes that by caching-effect >> thus deterring from expanding the same model as new data?)

removeComponent: unfortunately there doesn’t seem to be an autocompletion on ‘entity. … >> removeComponent’ in the editor (was/can be a guessing game), but will try off course

Works like a charm :slight_smile:

1 Like

PS: so works fine on the model itself, but the attached textures are troubling me still:

LoadExtGlbFullOwnTexture.prototype.unloadModel = function(){
    var app = this.app;
    var self = this;
  
           var meshes = null; 
           meshes = self.entity.model.model.meshInstances; 

                          for(var i=0; i<meshes.length; i++){ 
                              var mesh = meshes[i];
                     
                              console.log( ":: || "+ mesh.node.name + " chg "+i);

                              asset.unload(); //aproach 1: your suggestion but no change [err: on asset > how to assign asset, when external from start; then pushed to assets, for finally to be taken off leaving original texture?]
                              
                              self.entity.model.model.meshInstances[i].material.destroy(0);   //aproach 2: no change
                              self.entity.model.model.meshInstances[i].material.destroy(1);  ///aproach 2: no change
                              
                              self.entity.model.model.meshInstances[i].material.diffuseMap = null; // apporach 3: 'hail mary' ... no change
                              }
    self.entity.removeComponent("model");   
};

Was wondering if I should go in this direction;

  • but as yauStar writes/wrote below the thread seems to be part of a repo debug-issue.
    As such there might be a easier way to handle material/texture resets? (would not dare to use time, examples/solutions that has become impossible to a later repo)

Anyways: I got it working but end-solution will not work by a ‘simple list run through’ :-/

  • here is the working line so far:

var asset = self.app.assets.find ("127p.jpg"); asset.unload();

Which means I have to do a list the hard way - metacode:

var listOfAssetNames ->> push-name-for-each-time-I-load-an-external-texture ->> if-reset-runthrough-by;asset.unload-foreach-name-in-pushedlist


post-edit >> end-solution:
At write-in (push):

           var toSplit = self.app.root.findByName("ModelLoad").script.ui.textField_Texture;
           var astidSplitFRWSLASH = toSplit.split('/');  //console.log("ASTID: "+assetTex.id); 
           console.log("AS: "+astidSplitFRWSLASH[astidSplitFRWSLASH.length-1]);
           self.assetNameList.push(astidSplitFRWSLASH[astidSplitFRWSLASH.length-1]);
  • and at reset:
LoadExtGlbFullOwnTexture.prototype.unloadModel = function(){
    var app = this.app;
    var self = this;
  
                     for(var i=0; i<self.assetNameList.length; i++){
                             console.log( "AAA "+  self.assetNameList[i]);
                             var asset  = self.app.assets.find(self.assetNameList[i]);
                             asset.unload();
                            }

    self.entity.removeComponent("model");   
};
1 Like

Why not keep a reference to the asset(s) when you load them? Wouldn’t that make it a lot easier?

hmm … do you have an example? … not sure regarding the details of your proposal

Let’s take one of your code samples:

app.assets.loadFromUrlAndFilename(recUrl, null, "container", function (err, asset) {
});

The asset is passed in via the callback so all that needs to be done is keep a reference to the asset in some way. eg

var self = this;
app.assets.loadFromUrlAndFilename(recUrl, null, "container", function (err, asset) {
    self._recAsset = asset;
});

Later in the script to unload it:

this._recAsset.unload();

Or access the material assets from the container and unload them individually.

but if the object has 8 material-slots, and I want the user to be able to reset them all at once … and not in the same scripts?
I can tell the smartness of the ‘hanging’ callback effect, but here I am using another independent class/script than the one that loads - well, it works for me now, but will take a look upon your structure another time / in a more fitting scenario :slight_smile: (I am after all not an expert in some certain grips in here like namely callback, components …)

You can also assign a tag to the assets so other scripts can use findByTag to get all the assets that have that tag.

In the example of 8 materials, you can loop through all the material assets, tag them with a string, eg rec materials. Then in the other script, you can use findByTag to get an array of all the material assets.

There’s a number of ways that this could be done including keeping it all in the same script and using PlayCanvas events to tell another script to unload.

My 3D Bitmoji Library project does a bit of work around keeping track of loaded assets and unloading when entities are destroyed. https://playcanvas.com/project/721733/overview/3d-bitmoji-library

This file in particular: https://playcanvas.com/editor/code/721733?tabs=35751988

1 Like