3.x中Tween结合Material实现模型逐渐透明的一点思路

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

20221202_093351 00_00_00-00_00_30

被“切割”而翻滚掉落逐渐消失的方块,那么我们就会陷入一个僵橘!
掉落的方块的位移与旋转我们可以使用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的,这么麻烦呢?
请看下图!

这就是为什么我们绕了这么大一圈的原因,既然要做,就做好一点!!

好了,最后就是如何使用了!

相信聪明的小伙伴应该都能看懂!

3赞





我用tween以后,会被debugger拦住,如图所示。直接设置mainColor就没有问题,怎么回事儿 :rofl:


这里正常应该是true,但是使用tween后返回了false

:rofl:你这情况真神奇,其实我写的这个TweenMaterial只是个包裹的作用,类似于中间商,一层代理,借用get/set方法,来实现可以结合Tween使用。你看看能跟进去看到那个validator的细节吗,应该是个检测value是否符合规范的函数。传入一个Vec4给mainColor应该是没问题的啊

破案了,不知为何,tween传的值不是Vec4,new一个Vec4就好了。

:rofl: :rofl: :rofl:

mark!