开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2212

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 4358|回复: 69

[士郎] 快速实现数据编辑器——不要再傻傻地用代码一行行绘制界面了

[复制链接]  [移动端链接]
排名
3
昨日变化

6378

主题

6892

帖子

2万

积分

Rank: 16

UID
1231
好友
185
蛮牛币
2775
威望
30
注册时间
2013-7-29
在线时间
3267 小时
最后登录
2018-5-25

社区QQ达人活力之星原创精华达人突出贡献奖财富之证游戏蛮牛QQ群会员蛮牛妹VIP

发表于 2018-1-30 13:48:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
我最开始做编辑器的时候,确实也是用EditorGUILayout一行一行写的。


Unity的EditorGUI这套东西,在实现界面上确实上已经比传统的“拖控件+设属性+加监听”要快多了,确实容易就此满足。尤其是以前回合制游戏的编辑器,其实也就是个单层数组,工作量并不大。


而从客户端过来的人,因为以前引擎稀烂,本来就要设专人用大量精力做编辑器,他们认为在这种地方浪费时间是理所应当的。反正工期也长,既然有专门做编辑器的人,让他们闲着也不好。


直到——之前项目的策划非要我在项目原型阶段拿一个编辑器出来,而且还是照抄别的游戏的整套功能的那种,大概是个包含各种定制功能的弹幕游戏,内置Action,Trigger和其他奇怪的玩意儿。如果用普通的方式,几十个类,没有一万行代码怕是搞不定。


而我最多也就一周时间。


虽然明明可以用编辑xml文件等序列化数据文件的方式来代替,但他们硬要有编辑器才开始工作,似乎觉得编辑器是弹个响指一夜之间变出来的玩意儿。不考虑工具性价比也是中国策划的通病了。


我当时也没有别的办法。由于之前的数据格式是XML(直接从竞品偷的),我便根据文件内容整理出了一个表述数据结构的XML,然后写编辑器代码读取这个XML并生成整个树状界面,这样就不用一个一个类去实现了,再加上一些拖拽Asset,预览等需求,大概用了三天便完成了这个功能。
由于后期的编辑器修改需求无非就是增减属性,增删Class。直接改下那个作为配置的XML文件就可以了。所以编辑器方面就无需再花费精力,后来那个XML文件都直接交给策划自己改了。毕竟等我改需要时间,他们即改即用。


反正是非常的好用。之前老老实实一条一条写代码的我就和傻逼一样。
而且很显然,这东西是通用的,放任何项目里只要花个个把小时改下XML文件就能把功能实现出来,除了略丑之外,和其他项目用专人跟进整个项目搞出来的东向并没有啥区别。


但是这个东西毕竟也算项目代码,不太合适直接放出来,所以这里我说的其实是和它无关的后续事项。

——虽然之前的方案用起来是挺方便,但它是“完全”的吗?

其实并不是。


因为这个配置文件和实际用的数据类是分开编写的。每增加一个属性,虽然编辑器那边不需要我插手,但我还是需要修改实际的数据类,并修改对应部分的Parse代码才可以完成这个更新流程。编辑器那边可以偷懒用字符串,程序里却还是只能用枚举。


也就是说,编辑器端的配置文件和我这边的数据类以及Parse代码依然是完全重复的劳动。

在我的既有“世界观”里,对数据文件写Parse代码转换成数据类是一件理所应当的工作,花的时间也不长,便止步于此。但现在看来,我这样的想法,又和认为“反正编辑器需要有一个人专门跟进,便连显而易见的效率改进都不做”的人有什么区别呢?


[AppleScript] 纯文本查看 复制代码
[CustomEditor(typeof(Type))]



这是所有写过编辑器的人非常熟悉的一行代码,因为它是编辑器的入口。

但是:

[AppleScript] 纯文本查看 复制代码
[CustomPropertyDrawer(typeof(Type))]


恐怕就没几个人知道了。

它和CustomEditor功能类似,都是自定义特定类型的编辑器界面,但它的对象不是MonoBehaviour,而是一个字段上的数据。

[AppleScript] 纯文本查看 复制代码
[CustomPropertyDrawer(typeof(UserStruct))]
public class UserStrutDraw : PropertyDrawer
{
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return 0f;
    }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PropertyField(property.FindPropertyRelative("name"),new GUIContent("姓名:"));
        EditorGUILayout.PropertyField(property.FindPropertyRelative("sex"),new GUIContent("性别:"));
        EditorGUILayout.EndHorizontal();
        EditorGUI.EndProperty();
    }
}


创建这样一个类后,用到UserStruct这个数据的编辑器界面都会发生变化(或者是公开属性直接在属性面板显示,又或者是用EditorGUILayout.PropertyField呈现)

但这样并不方便,因为同一段编辑器代码会用在多个类型上,所以通常的做法是:[CustomPropertyDrawer(typeof(Type))]中的Type不指定具体类型,而是指定一个PropertyAttribute元标签对象。

[AppleScript] 纯文本查看 复制代码
public class UserDisplayAttribute : PropertyAttribute
{
}
然后在需要应用应用这个编辑器的地方打上UserDisplayAttribute这个元标签。
[AppleScript] 纯文本查看 复制代码
[System.Serializable]
public class Profile
{
      [UserDisplayAttribute]
      public UserStruct user;
}

便能够有和之前相同的效果。

此外,编辑器类的基类PropertyDrawer是用来定义某个属性的,它具有独占性。但你也可以继承自DecoratorDrawer,它是“装饰”的意思,是可以叠加的,可以用它来做一些界面绘制工作。

[AppleScript] 纯文本查看 复制代码
[System.Serializable]
public class Profile
{
      [DrawLine]
      [UserDisplayAttribute]
      public UserStruct user;
}

另外,Attribute对象也是可以有内部属性的
[AppleScript] 纯文本查看 复制代码
public class UserDisplayAttribute : PropertyAttribute
{
     public Color color;
}


直接写在括号内就可以为这些属性赋值,然后就可以在相应的PropertyDrawer类里读取到这个值,并处理。

[AppleScript] 纯文本查看 复制代码
[System.Serializable]
public class Profile
{
      [DrawLine]
      [UserDisplayAttribute(color = Color.red)]
      public UserStruct user;
}

这就为我们开通了另一条,不通过CustomEditor做界面的方法。而这种方法代码量更少,也更容易重用。我们可以在写数据类的时候顺便加上这些元标签,然后用EditorGUILayout.PropertyField呈现整个数据类的根结点,然后用Unity自己的对象层级功能一层层展开,不需要为每条属性书写编辑器代码。对Unity自带呈现不满的地方,用PropertyDrawer类重新定义就可以。

数组也是可以重定义的。

而且用这种方法,以前一些比较麻烦的组件功能也变得容易实现了,诸如Tab

[AppleScript] 纯文本查看 复制代码
[CustomPropertyDrawer(typeof(TabAttribute))]
public class TabDraw : PropertyDrawer
{
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return 0f;
    }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        GUIStyle buttonActive = new GUIStyle(GUI.skin.button) { normal = GUI.skin.button.active };
        string[] tabNames = (attribute as TabAttribute).tabNames;
        EditorGUILayout.BeginHorizontal();
        int count = tabNames.Length;
        for (int i = 0; i < count; i++)
        {
            if (GUILayout.Button(tabNames, i == property.intValue ? buttonActive : GUI.skin.button))
            {
                property.intValue = i;
            }
        }
        EditorGUILayout.EndHorizontal();
    }
}
public class TabAttribute: PropertyAttribute
{
    public string[] tabNames;
}

//使用示例
[Tab(tabNames = new string[] { "tab1","tab2"})]
public int tabIndex;


1.jpg



还有比较重要的属性中文化

[AppleScript] 纯文本查看 复制代码
[CustomPropertyDrawer(typeof(LabelAttribute),false)]
public class LabelDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        label.text = (attribute as LabelAttribute).label;
        EditorGUI.PropertyField(position, property, label);
    }
}
public class LabelAttribute : PropertyAttribute
{
    public string label;
    public LabelAttribute(string label)
    {
        this.label = label;
    }
}[/p][p=30, 2, left][Label("中文属性名")]
public int testInt;

2.jpg



所以我们只需要写好数据类,然后适当加几个样式元标签,根据游戏内容自己实现一些特殊的元标签以便和游戏预览部分通信,以及针对布局需求用DecoratorDrawer绘制界面。然后外面再包一个EditorWindows,将游戏的数据用ScriptableObject整体序列化以及储存。


这样我们在游戏开发过程中,编辑器就可以自动完成了,数据部分也是高效的二进制序列化格式,读取即使用,也不需要重写一遍Parse。


要说缺点的话,也就是限死了必须用Unity的序列化格式。当然,如果你愿意的话,也可以写个反射脚本把它转换成JSON,XML等其他格式,但在“技能编辑器”这类应用环境内,由于只有客户端在使用,并不需要“通用性”(虽说这个格式C#也能内建读取就是了)


至于你说,策划和程序用的是不同的Unity工程,所以不能用一样的数据格式……


首先策划和美术起码得用一样的工程,否则同步资源太浪费时间了,不同步资源?是让策划瞎着眼睛配置数据吗?程序部分如果不想暴露代码,可以编译成DLL放到他们的工程目录内,这样用上去和使用同一工程是一样的。


你非要两边代码不共用,就意味着编辑器那边不仅要实现数据编辑,还要把部分游戏逻辑修改复制一份到另一边,很容易不一致,并导致委曲求全,编辑器使用非常困难。


关键是耗费巨大,又没有实际的好处。

只要编辑器和运行时使用同一套CS代码,就可以通过这套东西节约大量开发时间,以及需求变动时修改导致的等待时间。


然而,虽然有这套东西,但是Unity自己的原始属性面板确实比较难用,虽说都可以实现,但像Tab,数组之类的功能,一个个实现也很费时间


1.1.gif

进入网站往下拉可以看到全部功能介绍的动图。

除了大量定义好的元标签之外,还提供了一个任意类型序列化的功能,便于容纳字典等其他复杂类型。
从源码看,它还重写了Unity的那套Attribute的底层,不再限制元标签必须在字段上,可以放到方法上实现诸如Button之类的功能。
[AppleScript] 纯文本查看 复制代码
[Button("label")]
public void TestMethod()
{
    Debug.Log("test");
}

在它的基础上开始扩展,应该是更好的做法。

知乎@flashyiyi

本帖被以下淘专辑推荐:


跟我念“站长妹纸萌萌哒!”我说站长,你说YO!爱你们么么哒~
回复

使用道具 举报

7日久生情
1857/5000
排名
807
昨日变化
2

4

主题

128

帖子

1857

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
29196
好友
0
蛮牛币
2526
威望
0
注册时间
2014-6-11
在线时间
645 小时
最后登录
2018-5-3
发表于 2018-1-30 14:37:37 | 显示全部楼层
楼主 请教下 这个动图中tab 切换的动态效果怎么做的
CustomPropertyDrawer 中好像很多EditorGUILayout中的方法不能用 需要repaint
但是PropertyDrawer 又不能repaint
能否给段gif中的代码参考下
谢谢

回复 支持 反对

使用道具 举报

4四处流浪
370/500
排名
12289
昨日变化
6

3

主题

133

帖子

370

积分

Rank: 4

UID
216830
好友
2
蛮牛币
211
威望
0
注册时间
2017-4-9
在线时间
170 小时
最后登录
2018-5-17
发表于 2018-1-30 14:54:56 | 显示全部楼层
谢谢分享
[发帖际遇]: wx_Zh7tc9i4 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
2082/5000
排名
3552
昨日变化
15

7

主题

1093

帖子

2082

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
168159
好友
4
蛮牛币
6066
威望
0
注册时间
2016-9-12
在线时间
614 小时
最后登录
2018-5-25
发表于 2018-1-30 15:33:20 | 显示全部楼层
[发帖际遇]: ceshi12580 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
3027/5000
排名
289
昨日变化

2

主题

299

帖子

3027

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
38772
好友
8
蛮牛币
4681
威望
0
注册时间
2014-8-8
在线时间
1020 小时
最后登录
2018-5-18
QQ
发表于 2018-1-30 16:14:11 | 显示全部楼层
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

回复 支持 反对

使用道具 举报

5熟悉之中
551/1000
排名
4428
昨日变化
3

0

主题

65

帖子

551

积分

Rank: 5Rank: 5

UID
120241
好友
3
蛮牛币
838
威望
0
注册时间
2015-8-29
在线时间
199 小时
最后登录
2018-5-23
QQ
发表于 2018-1-30 16:42:51 | 显示全部楼层
转帖请标注一下可好. 蛮牛是个我喜欢的论坛.但是不加标注的转载 是不是过分了点

点评

下方已经注明,谢!  发表于 2018-1-30 17:48
[发帖际遇]: wmh49877 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
726/1000
排名
11347
昨日变化
3

13

主题

129

帖子

726

积分

Rank: 5Rank: 5

UID
121896
好友
0
蛮牛币
705
威望
0
注册时间
2015-9-9
在线时间
504 小时
最后登录
2018-5-25
发表于 2018-1-30 17:00:55 | 显示全部楼层
能分享一个demo出来看看嘛

回复 支持 反对

使用道具 举报

4四处流浪
340/500

0

主题

215

帖子

340

积分

Rank: 4

UID
109564
好友
0
蛮牛币
94
威望
0
注册时间
2015-6-20
在线时间
125 小时
最后登录
2018-2-9
发表于 2018-1-30 17:34:34 | 显示全部楼层
做成产品了吧

回复

使用道具 举报

3偶尔光临
182/300
排名
16245
昨日变化
8

0

主题

73

帖子

182

积分

Rank: 3Rank: 3Rank: 3

UID
259499
好友
0
蛮牛币
78
威望
0
注册时间
2017-12-13
在线时间
75 小时
最后登录
2018-2-26
发表于 2018-1-30 20:49:55 | 显示全部楼层
6666666666666666666666666666666666666666666666

回复 支持 反对

使用道具 举报

3偶尔光临
188/300
排名
10076
昨日变化
3

0

主题

27

帖子

188

积分

Rank: 3Rank: 3Rank: 3

UID
175798
好友
0
蛮牛币
146
威望
0
注册时间
2016-10-15
在线时间
69 小时
最后登录
2018-4-26
发表于 2018-1-31 06:50:01 | 显示全部楼层
感觉真是牛x了!这才是脑阔里有想法并敢于付诸实践的人!

回复 支持 反对

使用道具 举报

7日久生情
2533/5000
排名
3334
昨日变化
2

2

主题

1780

帖子

2533

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
241666
好友
0
蛮牛币
10193
威望
0
注册时间
2017-9-6
在线时间
360 小时
最后登录
2018-5-23
发表于 2018-1-31 07:48:27 来自Mobile--- | 显示全部楼层
感谢分享

回复

使用道具 举报

7日久生情
2503/5000
排名
420
昨日变化

0

主题

521

帖子

2503

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
88896
好友
0
蛮牛币
9782
威望
0
注册时间
2015-4-2
在线时间
522 小时
最后登录
2018-5-25
发表于 2018-1-31 08:19:37 | 显示全部楼层
看样子还得逼你,不逼出不了活。
[发帖际遇]: David_who 捡了钱没交公 蛮牛币 降了 3 . 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

7日久生情
2503/5000
排名
420
昨日变化

0

主题

521

帖子

2503

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
88896
好友
0
蛮牛币
9782
威望
0
注册时间
2015-4-2
在线时间
522 小时
最后登录
2018-5-25
发表于 2018-1-31 08:20:53 | 显示全部楼层
说的不对吗
[发帖际遇]: 一个袋子砸在了 David_who 头上,David_who 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

4四处流浪
476/500
排名
5063
昨日变化
2

3

主题

122

帖子

476

积分

Rank: 4

UID
237362
好友
0
蛮牛币
1924
威望
0
注册时间
2017-8-13
在线时间
105 小时
最后登录
2018-5-15
发表于 2018-1-31 09:11:56 | 显示全部楼层
666666666666666666666666666666666+
[发帖际遇]: 专业找茬的 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

7日久生情
2175/5000
排名
1409
昨日变化
1

4

主题

570

帖子

2175

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
112674
好友
4
蛮牛币
1290
威望
0
注册时间
2015-7-8
在线时间
813 小时
最后登录
2018-5-25
QQ
发表于 2018-1-31 09:19:45 | 显示全部楼层
快速实现数据编辑器——不要再傻傻地用代码一行行绘制界面了
[发帖际遇]: zakieeva 捡了钱没交公 蛮牛币 降了 2 . 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表