Cocos Creator 巧用装饰器,给你的属性检查器面板加点「料」

共 3113字,需浏览 7分钟

 ·

2022-02-28 16:32

引言:如何让你的数据在属性检查器(Inspector)里以滚动条、下拉框、颜色盘、复选框等方式展示?如何提高数据直观度和约束能力,提高使用者(特别是非程序员)的生产效率?如何在属性检查器面板中展开自己写的自定义类属性?今天这篇文章将解答你的疑问。



属性检查器面板是我们在使用 Cocos Creator 中最常用到的功能面板之一,便捷的操作能让我们的开发更加省力。那么在使用的时候,小伙伴们有没有想过它的实现原理?自己是否可以实现出相同的效果呢?如何将自定义的 class 也显示到属性检查器面板中呢?



最近菜鸟在开发中使用了 Cocos Creator 的装饰器来与 Inspector 面板结合实现,长话短说,直接见正文。


TypeScript 装饰器


首先咱们来了解一下 TypeScript 对装饰器的解释:在一些场景下我们需要额外的特性来支持标注或修改类及其成员,装饰器(Decorators)为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式。


从上边的解释中 我们可以提取到几个关键点:

  • 作用:标注或修改类及其成员

  • 作用目标:类及其成员(类,方法, 访问符,属性或参数)


继续往下了解,可以知道 TypeScript 装饰器大概存在:类装饰器、属性装饰器、方法装饰器、方法参数装饰器这几种。有关 TypeScript 装饰器的更多内容,小伙伴们可以自己查阅资料了解一下。


Cocos Creator 中的装饰器


这才是咱们今天讨论的重点。


从 TypeScript 成为 Cocos Creator 3.x 主要的开发语言开始,装饰器就成了大家必须要了解的内容。我们首先来认识一下序列化、Cocos Creator 的脚本编译时机与装饰器执行时机

  • 序列化:默认情况会将编辑器中设置好的属性值保存到场景等资源文件中,之后在加载场景时就会自动还原成设置好的属性值。

  • 脚本编译时机:小伙伴们可能都发现了,我们在外部脚本编辑器修改项目脚本后,重新返回 Cocos Creator 会自动的触发脚本编译。

  • 装饰器执行时机:修饰器对类的行为的改变,是代码编译时发生的(不是 TypeScript 编译,而是 js 在执行机中编译阶段),而不是在运行时。这意味着,修饰器能在编译阶段运行代码。也就是说,修饰器本质就是编译时执行的函数。


基本用法


组件类装饰器(executeInEditMode)


正常情况下,所有组件都只会在运行时执行,也就是说它们的生命周期回调在编辑器模式下并不会触发。如果需要在编辑器模式下就执行,可以使用组件类装饰器



属性装饰器(property)


属性编辑器的常见属性类型:

  • 基础属性:CCInteger、CCFloat、CCBoolean、CCString

  • cc 类型

  • 数组类型:[CCInteger]、[Node]


可见性


需要注意的是:不是所有定义的属性装饰器都是可见的。以下两种情况是不会显示在编辑器子中的:

  • 属性名是否以 _ 开头

  • visible 属性值为 false


序列化(serializable)


属性默认情况下都会被序列化,序列化后就会将编辑器中设置好的属性值保存到场景等资源文件中,之后在加载场景时就会自动还原成设置好的属性值。如果不想序列化,可以设置 serializable: false。

@property({ serializable: false })
num = 0;


get/set 使用


@property
_num:number=1;
@property({type:CCInteger,tooltip:"提示内容"})
set num(val){
    this._num=val;
}
get num(){
    return this._num;
}


以上内容将一些简单的,最常用的基本用法进行介绍,详细内容可以自行参考官方文档。


更多用法


下拉列表



滑动条


@property({type:CCFloat,slide:true,max:1.0,min:0.0,step:0.01})
slide:number=0.5;


自定义样式


样式一


样式二


enum Type {
    one = 1,
    two = 2,
    three = 3,
    four = 4,
    five = 5,
}
Enum(Type);
@ccclass('Test4')
@executeInEditMode(true)
export class Test4 extends Component {
    @property
    _type: Type = Type.one;
    @property({ type: Type })
    get type() {
        return this._type;
    }
    set type(val) {
        this._type = val;
        this.setType(val);
    }
    @property
    _num: number = 10;
    @property({
        type: CCInteger, visible: function (this{
            return this.isShowNum;
        }
    })
    get num() {
        return this._num;
    }
    set num(val) {
        this._num = val;
    }
    @property
    _str: string = "你好";
    @property({
        visible: function (this{
            return this.isShowString;
        }
    })
    get str() {
        return this._str;
    }
    set str(val) {
        this._str = val;
    }

    @property
    _bool: boolean = true;
    @property({
        visible: function (this{
            return this.isShowBool;
        }
    })
    get bool() {
        return this._bool;
    }
    set bool(val) {
        this._bool = val;
    }
    private isShowNum = false;
    private isShowString = false;
    private isShowBool = false;
    private setType(val): void {
       ...
    }

    onLoad() {
        console.log("onLoad");
    }
}

样式三




点击文末【阅读原文】下载完整 Demo。本文首发在菜鸟的公众号「搬砖小菜鸟」,欢迎关注、交流,查看更多引擎技术干货!


往期精彩
浏览 120
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报