在2.x中如果要实现某张图片的渐隐效果是一件很简单的事情,使用tween改变节点的opacity值即可。
在3.x中,如果像实现类似效果,改变某个模型的透明度,则需要设置模型对应材质的mainColor(或者其他)property。
But,如果要实现连续变化,比如下面这个

被“切割”而翻滚掉落逐渐消失的方块,那么我们就会陷入一个僵橘!
掉落的方块的位移与旋转我们可以使用tween来实现,但是透明度我们只能通过update或者schedule来不断改变方块材质的mainColor来实现,这显然不是一个最优解。那么我们是否可以将材质的property的改变“集成”至tween中呢?答案是肯定的。
因为tween的本质就是在细分的时间段内,改变对象的某个属性,那么我们可以将材质(或者说用到该材质的节点),包裹为一个对象,通过set和get方法的包裹,实现对材质某些属性的不断改变。
废话不多说直接上代码!
import { Node, Material, MeshRenderer, Vec4, renderer, assert, IVec4Like } from "cc";
export class TweenMaterial {
private node: Node = null;
private renderer: MeshRenderer = null;
private material: Material;
private pass: renderer.Pass = null;
private mainColorHandler: number = 0;
private _mainColor: Vec4 = null;
constructor(node: Node, initialColor?: IVec4Like) {
this.node = node;
this.renderer = this.node.getComponent(MeshRenderer);
this.material = this.renderer.getMaterialInstance(0);
this.pass = this.material.passes[0];
this.mainColorHandler = this.pass.getHandle('mainColor');
if (initialColor) {
this._mainColor = Vec4.clone(initialColor);
this.pass.setUniform(this.mainColorHandler, this._mainColor)
} else {
this._mainColor = new Vec4();
this.pass.getUniform(this.mainColorHandler, this._mainColor);
}
}
get mainColor() {
assert(this.node !== null);
return this._mainColor;
}
set mainColor(v: Vec4) {
this.pass?.setUniform(this.mainColorHandler, v);
}
}
此处略作分析。
通过构造函数constructor传入一个Node,通过Node,依次获取Node上的MeshRenderer组件,以及组件用到的材质实例(防止影响到其他用到该材质的方块)。然后通过材质的passes获取到我们这里需要的第一个pass,至于为什么,请看下图
我们这里copy一份默认的default-material材质出来修改,注意要实现透明,Technique需要选择为transparent。
要实现透明度的更改,我们需要改变pass0通道的albedo color。为什么这里是albedo而不是mainColor,这个问题其实写在了该材质对应的effect文件中,请看
mainColor在编辑器中展示为albedo……
扯远了。。。我们继续说回刚才的代码
获取到pass0之后,我们还需要获取mainColor这个属性对应的handler,下面要用。
然后就是set方法设置mainColor了,此处我们只需要简单调用pass的setUniform方法,即可实现对材质颜色的改变。
OOOOOOOOOK写到这里,可能有人疑惑,为什么我们不直接用Material提供的setProperty方法,而是绕了这么大一圈,又是pass,又是handle的,这么麻烦呢?
请看下图!
这就是为什么我们绕了这么大一圈的原因,既然要做,就做好一点!!
好了,最后就是如何使用了!
相信聪明的小伙伴应该都能看懂!








