How to change material on click of a button?

I have a car model which has 20 materials in it and I want to change the 3rd material in the array to something else. But my code is not working its showing(Uncaught TypeError: Cannot read properties of undefined (reading ‘material’).
Here is my code any kind of help will be appreciated :slight_smile:

FtypeUi.attributes.add('car', {
    type: 'entity',
    assetType: 'model'
});
FtypeUi.attributes.add('mat1', {
    type: 'asset',
    assetType: 'material'
});

FtypeUi.attributes.add('mat2', {
    type: 'asset',
    assetType: 'material'
});

FtypeUi.attributes.add('mat3', {
    type: 'asset',
    assetType: 'material'
});

// update code called every frame
FtypeUi.prototype.update = function(dt) {


    this.color1.button.on('click', function(event) {

        var mats = this.car.findComponents('render');

        mats.material = this.mat3;
    }, this);

    this.color2.button.on('click', function(event) {

        var mats1 = this.car.findComponents('render');

        mats1.meshInstances.material[2] = this.mat2;
        
    }, this);

    this.color3.button.on('click', function(event) {

        var mats = this.car.findComponents('render');

        mats.material = this.mat3;
        
    }, this);

    

};

Hi @Vivek_Chaini and welcome! I’m not totally sure, but I think it’s because you search for a render component to get the material while you use a model component for your car entity.

hello @Albertos then what should i do here. Any suggestions on how to change the one specific material from material array of the model?

You can try to change your asset type for the car entity to render or use this.car.findComponents('model') to get your materials.

Okay I will try this and get back to you :slight_smile:
Thanks

@Albertos can you show me the code for it I am very new in JavaScript and this playcanvas engine. It will be very helpful you can take the reference from my code. I have been struggling for past 2 days.

Thanks

If you go for this option you have to change line 26, 33 and 41 of the code above to find component model instead of render.

Used this @Albertos

this.color2.button.on('click', function(event) {

        var mats1 = this.car.findComponents('model');

        mats1.meshInstances[2].material = this.mat2;
        
    }, this);

showing this error “Uncaught TypeError: Cannot read properties of undefined (reading ‘2’)”

How many meshInstances does you model have?

It has 20 materials @Albertos

Oh wait. Seems that meshInstances is undefined now and that’s probably because you use the render component at the moment. If you use a render component you need to use findComponent('render') and if you use a model component you need to use findComponent('model').

Do you mean findComponent rather than findComponents?

1 Like

@Kulodo133 Yea its confusing.What i need to do is change the one specific material from material array of the model. I tried different things but nothing seems to work im very new at this. Please tell me how can i achieve this.

@Albertos I used asset type as model and findComponent(‘model’) its showing this error i click the button “Uncaught TypeError: Cannot read properties of null (reading ‘meshInstances’)”

Because you use a render component and not a model component at the moment. That means that findComponent(‘model’) will be undefined.

1 Like

Okay instead of model i will use render in asset type and find components

1 Like

It says Error loading scripts. Open the browser console for details. when i used this

Okay instead of model i will use render in asset type and find components
:sweat_smile: :sweat_smile:

Can you share a link of your project please so someone can take a look?

okay here is the link PlayCanvas | HTML5 Game Engine

Just a couple of issues:

  1. The button event listeners were being added in the update function of the script. Which means there was listeners being added every frame. I’ve moved them to initialize so they are only called once.
  2. mats1.meshInstances[2].material = this.mat2 - this.mat2 is the script attribute that references the material asset, not a material. Changing it to mats1.meshInstances[2].material = this.mat2.resource fixes the issue.

Fixed code here: https://playcanvas.com/project/974177/overview/f-carshowroom

2 Likes