Tween issue with material opacity

I am trying to fade out the “opacity” of a material from an entity, that is to decrease the “intensity” from 1 to 0. But unfortunately it is not able to get the property. What am I doing wrong here?

var PositionTrans = pc.createScript('positionTrans');

PositionTrans.attributes.add('targetSphere01', { type: 'entity' });
PositionTrans.attributes.add('duration', {type: 'number', default: 5.0});


// initialize code called once per entity
PositionTrans.prototype.initialize = function() {
    this.entity.button.on('click', function(event) {
        var tween1 = this.targetSphere01.tween(this.targetSphere01.material.opacity).to(0, this.duration, pc.SineInOut);
        tween1.start();
    }, this);
};

I get the error - Cannot read properties of undefined (reading 'material').

Hi @saifs ,

The tween library relies on JSON objects in order to manipulate values.

The first thing that you would want to do is define the opacity value you want to manipulate, something like this.opacity = {value: 1}

Then tween that specific value:

this.exampleEntity.tween(this.opacity)
     .to({value: 0.0}, 1.0, pc.Linear)

Of course this doesn’t actually change the material, just the value you provided. To then use your new value, you can apply it on the tween’s update event like this:

this.exampleEntity.tween(this.opacity)
     .to({value: 0.0}, 1.0, pc.Linear)
     .on('update', function(dt) {

     }.bind(this)

The other problem is that you will want to access the material through the geometry that is attached to the entity. This could be a model component or render component depending on whether you’re using legacy models. In the end it would look something like this:

this.exampleEntity.tween(this.opacity)
     .to({value: 0.0}, 1.0, pc.Linear)
     .on('update', function(dt) {

          this.exampleEntity.render.meshInstances[0].material.opacity = this.opacity.value;

          this.exampleEntity.render.meshInstances[0].material.update();

     }.bind(this)
     .start();

This code was written very quickly and does not account for models with more than one mesh instance on a model, but it should give you a pretty good idea of what’s happening.

In the meantime, for a more fleshed out example of working with model materials, check out this example project:

https://playcanvas.com/project/437442/overview/switching-materials-at-runtime

1 Like

Thank you so much for a detailed explanation. I unfortunately have still the issue:

var tween = this.targetSphere01_MAT.tween(this.targetSphere01_MAT.render.meshInstances[0].material.opacity).to({value: 0}, 1.0, pc.Linear);
tween.start();

The above code does not work but when I do this:

this.targetSphere01_MAT.render.meshInstances[0].material.opacity = 0;

it works. What am I doing wrong in my tweening?

I got it, I had to update the material as well.
Phew! This looks a complicated tweening :smiley:

 var opacity = {value : 1};
        
        this.targetSphere01_MAT.tween(opacity).to({value: 0.0}, 1.0, pc.Linear).on('update', function(dt) {
            this.targetSphere01_MAT.render.meshInstances[0].material.opacity = opacity.value;
            this.targetSphere01_MAT.render.meshInstances[0].material.update();
        }.bind(this)).start();
2 Likes

Check this example project as well, you will get better performance if you avoid using material.update() per frame:

meshInstance.setParameter("material_opacity", opacity);

https://developer.playcanvas.com/en/tutorials/fading-objects-in-and-out/

Note: For this to work make sure you set a material opacity different than 1.0 in the editor, to force the engine to include the relevant shader chunk:

image

2 Likes

Sorry about that! I forgot that you had to update the material after changing a property. Glad you figured it out!

I’ve edited my original answer to include this.

1 Like