基于Animator状态控制的UGUI开发规范

Last modified date

介绍我前几年整理的一套UGUI美术开发流程,用于剥离美术和程序的依赖关系。让美术,动画特效和程序可以分别工作,划清责任。

Unity3D是个简单好用的引擎,UGUI也越来越完善,但是开发复杂项目的时候还是会遇到很多坑,项目越做越复杂,UI资源缠在一起,变成个烂摊子。所以需要一开始就制定好合理的开发模式。这些年我总结了一套比较好用的UI开发流程,在以往几家公司的项目中都验证过,例如mihoyo的崩坏3的部分界面。我会用几篇文章分几部分讲述。

首先说说我在各个公司看到的“传统做法”存在的问题:

Prefab的命名规范和结构目录没有严格统一,带来如下问题:

  • 其他人比较难一下子看懂这个prefab,别人修改起来比较麻烦。
  • 相应的动画控制具体的实体对象的时候也会比较乱,一会儿控制容器,一会儿控制子对象,没有统一标准。虽然做的时候比较自由,但是后期扩展性很差,很难修改。

UI动画直接控制每个实体对象,这么做有一大堆缺点:

  • 以后添加/删除/重命名某个实体对象,那么相关动画就得重做,因为动画和实体对象的引用死死的绑定了。
  • 如果有2个动画结构基本相同的Prefab,但是因为Prefab目录的命名不一样,那么就得做2个Animation资源,比较浪费。

程序和美术都会去控制UI的动效,结果代码和美术资源粘在一起

  • 容易让美术和程序在UI开发里搞各种特例,你也控制一部分内容,我也控制一部分内容,最后开发了很多临时的功能,而且很杂乱。
  • 多人合作的时候流程杂乱,责任不清晰。
  • 以后内容扩展的时候很难把之前的东西再拆解,后期扩展受阻。

以上这些问题不仅是UI开发中会碰到,整个项目都是如此。

软件开发以前流行MVC模型之类的框架,就是为了让各个模块和工种之间的依赖关系尽量剥离,保证工作流的顺畅。我所用的这套框架也是基于这个思路的,不过我这里只介绍美术部分。

首先最重要的思路就是:

如何把美术的工作从程序那边剥离出来?

传统的国内团队都是有程序主导制作一套UI体系,然后UI美术按照要求给出资源,因为UI美术很少有会引擎会编程的,而且会动画特效的UI也很少,并且国内公司很少会专门配个UI动效。即使少数大型公司有专门的UI部门,也很少会自发制定一些UI自己的工作流。这就像人类历史,自己不强大,就会任人宰割。美术陪着程序加班赶项目都是家常便饭,痛苦吧。

那么废话少说,如何让UI美术“独立”呢?请看下图:

美术的工作包括UI Prefab和Animator。

  • 用Animtor制作各种UI Prefab中的效果:开关界面;现实/隐藏某些内容;按钮的多种状态切换;等等。
  • 以上状体在Animator中设置专属的状态ID,并且根程序同步一下。

程序的工作就是创建UI对象,获取其Animator组件,当状态变化时Set各种Animator的状态ID。

这样就基本剥离了美术和程序的依赖了:

  • 由于UI Prefab中的效果都是Animator控制的,所以界面拼好以后直接运行就能看到UI动效了。(通过手动修改Animator中的参数)
  • 程序不用管美术具体是怎么干的,最终UI效果不对或者动画不好看,可直接找UI美术去修改美术资源。如果是程序出错没有设置好Animator的状态,导致UI现实不正常就是程序自己的锅。责任分的很清楚,谁也别赖谁,周末别拖着美术一起加班。

好了,那么接下来具体说说我的详细做法。

命名规范:

首先最基本的就是命名,有些美术英文不好没关系可以用拼音,但是命名规范要一致。

Prefab命名:

按照“前缀_中缀_具体名称”方式命名,例如“UI_Panel_EnemyHP”。前缀说明时UI资源,中缀表示界面类型。

  • 前缀:(根据用途)

  • 中缀:(根据界面类型)

Prefab内部目录的命名:

这命名规范配合后面的Prefab结构,能一目了然每个部分的用途。

 

Prefab结构搭建的规则:
  • 示例:

 

  • 根据界面的功能模块分组,嵌套。目录可能会复杂一点,但是按照同一套思路去搭建,而且命名规范一致,再复杂的东西也不会看不明白。
  • 需要做动画的内容尽量套在一个容器下面,动画控制容器,尽量避免直接控制实体对象。这样做的好处是方便以后修改美术资源。例如增减图片文字就不用去修改动画了。

 

 

如何用Animator控制界面状态

用Animator中的参数切换UI的状态。程序不用关心Prefab中的具体内容,这个由美术自己控制。程序获取Anim_的引用,Set相应参数即可。

  • Prefab中的的组件的状态变化,都由Animator控制。
  • 具体状态参数要和程序确认。
范例1:

 

  • 顶层的根节点上的Animator“OpenAndClose”用来开关整个界面,是个通用的Animator,只控制自身的RectTranform和Con_Main的Enable属性。
  • 由于RectTramsform没有Enable属性,所以必须建一个Con_Main的根节点来作为开关整个界面的容器。这样固定的规范才能让Animator通用。

 

  • 上图就是Animator“OpenAndClose”。默认进入Disable状态,是个没动画的空状态。Open和Close分别是开关整个界面的动画。

  • Animator的Transition参数设置有几个要注意的。为了让切换过程没有动画混合,设置要按照上图。
  • Can Transition To Self是一定要取消的,否则动画反复从第一帧开始播。
  • 设置Conditions的时候要注意用Equals(等于)。

以上的步骤做好了界面的开关动效控制。

下面继续用Ainm_Main节点上的Animator用来控制几个模块的显示切换。

  • 用2个Layer来分别控制主模块和次级模块。之前的MainModule用来控制界面开关,现在再创建一个SubMudule的layer来控制三个次级模块的切换。

  • 默认进入DoNothing状态,是个没动画的空状态。大部分Animator都采用这种方式。
  • 设置2个参数分别控制2个Layer的状态切换,之前一个参数用来控制界面开关,再设一个参数用来控制3个次级模块的切换,详细的就不赘述了。

范例2

制作一个道具框,有品质变色的需求,这个变色功能在其他物品框的Prefab上也会用到,那么最好做一个通用的Animator。

  • 如上,一个简单的Item。在底板Img_ItemColor上面绑了Animator“SwitchItemColor”。

  • 4个动画分别对应4个颜色。以后只要这个结构和命名一致,就可以通用了。

好了以上就是基础的Animator做法。复杂的界面还有很多细节可以研究的,这篇先不深究了。

用这套思路,在美术风格还没有确定之前,可以先快速出个Alpha版本,以后再不断更新迭代,替换正式美术资源,而且拼图搭界面的工作是不会浪费的,因为美术资源本身也做到了结构与内容的依赖关系剥离。你看,试错和迭代成本都降低了。

 

最后再来说说UI资源文件目录规则:

目的是让目录结构一目了然,每个人都能快速找到资源位置。

Prefab的目录规则:

  • Prefab命名:如上所说,按照“前缀_中缀_具体名称”方式命名,例如“UI_Panel_EnemyHP”。
  • 通用的资源放在Common目录下
  • 各种UI组件的样板资源放在Sample目录下
  • UI组件的样板例如:按钮,拖动条,进度条,等等。
  • 每个功能模块的放在同名目录下
  • 临时资源放在Unfinished目录下,如果是某个开发人员专用的就在Unfinished目录下建一个自己名字的。临时UI的前缀用“TempUI_”,如果有多个临时版本就在最后加“_1”。例如“TempUI_Panel_EnemyHP_1”这样保障Unfinished目录以外的UI Prefab资源都是正式版的。
Animation目录规则:

  • 通用的动画放在Common目录
  • 每个功能相关的放在同名目录下
  • 每个UI Prefab专用的放在同名目录下
  • 如果还有内部单独的Animator,则放在一个同名目录下。
  • 非Animator类的老动画放在相关功能目录下的“Legacy”目录下。
  • 如果有多个动画版本存在,可在相关目录内部建立一个“V1.0”的目录,表示版本编号。注意每个版本要复制全套动画专用,不要与其他版本混用animation。
UI Prefab数量可以减少
  • 一个功能的UI资源,如果是会同时显示的,可以尽量做在一个Prefab里,没有必要分成多个。如果是通用的资源可以单独做一个Prefab。
  • 太多的Prefab管理起来非常麻烦。
  • 从性能考虑,除了会异步加载的资源,其他都做在一个Prefab里一起加载也没什么问题。
  • 新的Unity版本可以把Scene作为Assets对象来加载,多个UI资源甚至可以做在一个Scene里来加载使用。例如把一个有很多不同类型的页面内容的界面做在一个Sceen里,用个单独的Canvas显示。
其他注意点:
  • UI的Animation尽量少控制Alpha渐变。这个比较耗性能。如果并发数量较多的话,建议用缩短动画速度和缩放的方式来做。只要肉眼看上去感觉没问题就行。
  • Animator是用来做动画状态控制的。如果只有一个动画的话,就直接用老版Animation即可。

 

好了以上就是这套流程的基本开发方式。跟多的细节根本讲不完,而且unity还在持续更新中,未来肯定还有更好的开发模式。

另一个问题就是UI美术看这篇文章可能会很懵逼。“妈蛋看了半天原来我还要学引擎学动效!越来越累!”其实并不是强制每个人都要学技术的。这套流程可以一个人全搞定,也可以一个团队来做,UI美术依然只做图片资源,然后拼界面的人在引擎里按照规范来拼,最后特效人员去加动效。这才叫合理的work flow。

其实这套流程的思想适用于很多其他内容的开发,例如复杂动作游戏中角色的动作控制系统,我会在其他文章里谈谈。