【Unity 2019】在编辑器的Project Settings窗口中添加自定义设置项

2020年05月26日 11:52 0 点赞 1 评论 更新于 2025-11-21 21:34
【Unity 2019】在编辑器的Project Settings窗口中添加自定义设置项

在Unity的新版本中,Project Setting的一系列配置项从Inspector中独立出来,单独形成了一个窗口。实际上,我们也能够将自己游戏里的一些配置工具整合到这个窗口中。

需求背景

在我编写的一个Unity开发框架中,存在大量配置文件(继承自ScriptableObject类的.asset文件)。在Unity上编辑.asset配置文件的方式较为特殊:需要在Project窗口中选中该文件,其配置内容才会显示在Inspector窗口中。

这种方式存在明显问题。例如,当你需要在配置文件中填写一个文件名时,需要去查找该文件,右键复制其路径。在查找文件的过程中,之前选择的配置文件会失焦(不再是activeObject),Inspector窗口上的配置选项也会随之消失。这时你可能会疑惑“我刚刚配置一半的东西哪去了”,然后不得不重新在众多文件夹中找到该配置文件并再次选中它。偶尔操作一两次还能忍受,但如果需要配置大量内容,这种操作方式就会让人十分烦躁。

最初,我们使用Odin插件创建了一个窗口,将开发框架中的配置文件整合在一起。这个窗口的功能和结构与Unity新推出的Project Settings窗口类似。不过,当时创建这个窗口时,Unity还未推出Project Settings窗口。

实际上,这个窗口本质上仍然是在操作那一堆.asset配置文件。但Odin是付费插件,如果要将开发框架分享给团队之外的人使用,就会面临问题。因此,我们产生了让开发框架脱离Odin也能使用的需求。

恰好Unity 2019发布了,我们想到可以尝试在检测到工程中没有Odin插件时,将配置文件整合到新的Project Settings窗口中。于是就有了这篇文章。

需要说明的是,Project Settings独立窗口是从2018.3版本就开始有的功能,并非2019版本的新功能。不过由于以往的经验,我们通常会默认推迟一个版本再使用新功能。

下面来看看最终实现的效果(这里先实现了一个)。

开始实现

定义配置文件类

首先,需要定义一个配置文件类。这其实就是一个普通的ScriptableObject类,其中包含的一些#if判断是为了让它在没有Odin插件时也能正常工作,可暂时忽略这些判断。

定义设置提供类

接着,需要在编辑器目录(Editor目录)下重新定义一个类,用于告知Unity编辑器:“我要在你的设置窗口中显示内容!”

其简单结构如下:在一个静态类中,使用“SettingProviderAttribute”这个特性标记一个静态方法(强调:必须是静态方法,和定义菜单类似),该方法要返回一个“SettingProvider”对象。这种实现原理与“[MenuItem(xxxxx)]”的定义方法类似,符合Unity一贯的风格。

实现上述代码后,我们可以看到定义的设置项已经生效,但其中还没有具体内容。在Project Settings窗口的Project目录下会出现一个名为“喵”的配置项,这是因为我们定义的路径是“Project/喵”,和菜单的规则一样,如果不以“Project/”开头,它将成为顶级目录。

填充设置项内容

接下来,我们要往设置项中填充内容。官方文档中提供了三种方法:

  • IMGUI方式
  • UIElement方式
  • 用一个子类继承SettingsProvider类

这里我们选择IMGUI方式,因为暂时不想编写CSS,对于简单布局而言,没必要将其复杂化。

编写好代码后,我们会发现这其实是经典编辑器UI写法的一种变体。就像平时编写编辑器UI一样,在OnGUI方法中使用“GUILayout/EditorGUILayout”类来绘制UI。

至此,一个自定义的设置项就完成了。实际上,在Preferences窗口中自定义内容也是基于相同的原理。

UIElement方式补充说明

举一反三,如果采用UIElement方式,需要在”activateHandler“这个回调中初始化UIElement的代码。需要注意的是,activateHandler的参数 “rootElement”,如果其中包含子元素,Unity会认为采用的是UIElement方式绘制UI,此时guiHandler回调将被忽略,不会触发。由于UIElement是新功能,很多人可能还未接触过,如果不理解这里的内容,可直接忽略。

总结

自定义设置项的方法其实不难理解,与编写编辑器UI类似。但麻烦之处在于,需要自己编写GUI并逐个实现.asset配置文件中的配置项,过程较为繁琐。相比之下,Odin插件实现的窗口更加便捷,获取.asset文件对象后,它可以自动反射其中的配置项并调整布局。例如,开头截图中的窗口,核心代码仅需几句话。

我认为Unity或许应该收购Odin并将其集成到编辑器中,因为Unity编辑器自带的一些功能使用起来不够便捷。