• 最新Cocos Creator 3.x 如何动态修改3D物体的透明度


    Cocos Creator 3.x 的2D UI有个组件UIOpacity组件可以动态修改UI的透明度,非常方便。很多同学想3D物体上也有一个这样的组件来动态的控制与修改3D物体的透明度。今天基于Cocos Creator 3.8 来实现一个可以动态修改3D物体透明度的组件Opacity3D。

    对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。

    一个3D物体如何才能够半透明显示呢?

    编写Opacity3D组件之前,我们先搞懂一个3D物体如何半透明的显示?其实这个原理很简单,满足两个条件就可以了:

    1. 3D物体所在的渲染队列为”透明队列”;
    2. 3D物体的frag片元着色的时候alpha的透明度在(0~1)之间;

    满足以上两个条件,3D物体就会半透明。条件(2)中需要片元着色时候的透明度为(0~1)之间是否一定要修改shader呢?答案是不需要,因为CocosCreator 3.x的标准Shader里面提供了一个mainColor的颜色属性,默认是白色,如果你修改mainColor的透明度,传入到shader后,frag片元着色器会叠加mainColor的颜色值,这样我们要修改物体的透明度,可以通过修改mainColor来实现。

    图1:内置shader中使用CPU传递过来的mainColor数据)

    我们自己来编写Opacity3D的时候,就利用shader的这个特性,如果自己开发的shader没有mainColor机制,又需要使用Opacity3D组件的时候,可以给shader添加mainColor的机制或修改代码使用类似的颜色变量。

    Opactity3D组件的具体实现

    找到要半透明的3D物体,创建一个材质,使用内置的build-unlit shader,它有mainColor机制。设置该物体材质的渲染队列为Transparent。如图所示:

    接下来添加Opacity3D组件到对应的节点,在编辑器上调节它的透明度,如下图:

    运行起来,Cube就半透明了。

    Opacity3D组件核心实现

    Opactity3D的核心实现其实非常简单,先上源码(Cocos Creator 3.8):

    1. import { _decorator, color, Color, Component, Material, MeshRenderer, Node } from 'cc';
    2. const { ccclass, property } = _decorator;
    3. @ccclass('Opacity3D')
    4. export class Opacity3D extends Component {
    5. @property
    6. private alpha: number = 255; // 【0, 255】
    7. @property
    8. isSharedMode: boolean = false;
    9. private matInstance: Material = null!; // 3D物体的材质;
    10. private mainColor: Color = null;
    11. public get Alpha(): number {
    12. return this.alpha;
    13. }
    14. public set Alpha(alpha: number) {
    15. this.alpha = alpha;
    16. this.mainColor.a = this.alpha;
    17. this.matInstance.setProperty("mainColor", this.mainColor);
    18. }
    19. protected onLoad(): void {
    20. // 初始化材质对象
    21. var mr = this.node.getComponent(MeshRenderer);
    22. var mat = mr.sharedMaterial;
    23. // end
    24. this.matInstance = mat;
    25. if(this.isSharedMode === false) {
    26. this.matInstance = new Material();
    27. this.matInstance.copy(mat);
    28. mr.setMaterial(this.matInstance, 0);
    29. }
    30. // 初始化我们的mainColor;
    31. // 注意:这里有个坑, 如果你从来没有修改过这个mainColor,虽然有白色,但是获取不到的;
    32. this.mainColor = this.matInstance.getProperty("mainColor") as Color;
    33. // console.log(this.mainColor);
    34. if(this.mainColor === null) {
    35. // 注意:[0~1], 【0, 255】
    36. this.mainColor = color(255, 255, 255, 255);
    37. }
    38. this.alpha = (this.alpha < 0) ? 0 : this.alpha;
    39. this.alpha = (this.alpha >= 255) ? 255 : this.alpha;
    40. this.mainColor.a = this.alpha;
    41. this.matInstance.setProperty("mainColor", this.mainColor);
    42. }
    43. }


    核心原理就是定义成员变量alpha,然后编写get/set,get获取返回aplah值,set 设置alpha值并同步到材质里面,编写get/set的主要目的是配合tween的机制。这里有个很重要的数据成员isSharedMode,我们大家都知道,当我们给一个材质改变参数的时候,所有使用改材质的物体的参数全部都改变了,有时候我们有100个物体,可能只要其中的1个物体改变透明度,其它不改变,这时我们就可以让isSharedMode为false,这样会单独的为每个物体创建一个材质对象实例出来。

    1. if(this.isSharedMode === false) {
    2. this.matInstance = new Material();
    3. this.matInstance.copy(mat);
    4. mr.setMaterial(this.matInstance, 0);
    5. }

    结合Tween来渐变的改变3D物体的透明度

    我们都知道Tween实际是一个模板机制,给定一段时间,来利用update不断地改变某个属性,只要这个属性有get/set。我们在Opacity3D里面实现了Alpha的get/set,所以就可以与Tween进行配合,做到渐变,代码如下:

    1. opt = effect.getComponent(Opacity3D);
    2. Tween.stopAllByTarget(opt);
    3. opt.Alpha = 255;
    4. t4.delay(0.4);
    5. t4 = tween(opt);
    6. t4.to(time, {Alpha: 0});
    7. t4.start();

    今天的分享就到这里了,这里是获取教程的项目源码。同时我在我们官网放了对应的公开课,地址如下,大家可以看下具体的视频教程。

    Creator 3.8 3D物体的透明度渐变 (bycwedu.com)

    输入QQ号后即可免费学习,无套路

    大家好,我是Blake,我们专注于为游戏开发人员的技术进阶,架构进阶,行业解决方案提供专业的课程指导与服务。我们课程经过9年多的更新与迭代,已经涵盖了CocosCreator 开发中遇到的绝大部分问题,涵盖了CocosCreator主程序进阶,升职加薪所需要的系统的知识体系,主流游戏类型的重点难点技术解决方案。我们的老师10:00~23:00提供实时解答与回复,包含但不限于客户端+服务端。相信我们提供的游戏开发技术服务能很好地帮助到您。选择我们的VIP课程,您肯定不会后悔!

    谢谢大家

  • 相关阅读:
    Vue3最佳实践 第六章 Pinia,Vuex与axios,VueUse 4(axios)
    理解docker [一] - control group
    【C语言】归并排序
    R语言ggplot2可视化:使用ggpubr包的ggboxplot函数可视化分组箱图、使用set_palette函数同时改变可视化图像的线条色和填充色
    ceph-ansible5.0部署文档
    Visual Studio 安装离线插件 vsix 及常用插件
    我用ChatGPT做WebRTC音视频性能优化,主打一个高效
    在CARLA中手动开车,添加双目相机stereo camera,激光雷达Lidar
    2019年Java面试题汇总
    DDD领域驱动设计
  • 原文地址:https://blog.csdn.net/voidinit/article/details/134259936