Unity 操作小技巧:教你在开发时如何避开编辑器的那些坑
以下总结的内容一部分源于个人经验,一部分来自他人分享。总体而言,Unity 在开发原型、呈现效果以及验证想法方面极为便利,可能仅需一个月就能完成核心玩法的开发。其强大的编辑器功能为我们提供了广阔的可扩展空间,有助于开发各类工具。然而,编辑器犹如一把双刃剑。提前了解可能遇到的问题,借鉴他人的踩坑经验,将对项目风险的把控大有裨益。
避开 Unity 的坑
1. 制作抽象的 Prefab 进行关卡编辑
在进行关卡编辑时,应尽可能制作抽象的 Prefab。该 Prefab 需足够简单抽象,例如仅包含一个 GameObject,通过 Gizmo 进行绘制是个不错的方法。若 Prefab 设计复杂,当后续需要更改(常见的如修改美术资源)时,所有引用该 Prefab 的关卡可能会出现“lost prefab”的情况,这对策划人员来说将是一场灾难。可以考虑采用数据表与编辑器结合的方式,为策划人员提供操作便利,同时避免“lost prefab”的问题。此外,Prefab 越简单抽象,越不容易丢失,Prefab 之间的嵌套应通过链接而非挂载在节点下。
2. 尽可能避免修改 Scene
可采用以下几种方法避免直接修改 Scene:
- 使用 XML 等数据格式来组织场景。
- 尽量让 Scene 由 Prefab 组成,这样场景的变动可集中在 Prefab 上。
- 利用工具进行场景合并。
3. 避免过度依赖 Component 特性开发,采用数据驱动
在开发过程中,不应过度依赖 Component 特性,而应考虑采用数据驱动的方式,以提高代码的可维护性和灵活性。
4. 对逻辑进行中心管理
由于逻辑容易分散在编辑器的各个角落,建议进行中心管理,便于代码的维护和管理。
利用 Unity 的特性
组织好 Hierarchy
在编辑和运行时,都应组织好 Hierarchy。编辑时可借助工具简化组织层级的工作。
让每个场景独立运行
确保每个场景都能独立运行,提高开发和测试的效率。
基于组件的架构开发
在使用 C# 开发时,应利用基于组件的架构,尽量减少继承的使用,多通过组合的方式完成开发。当需要数据访问的通用接口时,可通过组合公共组件来获取数据,而非继承公共基类接口。对于通用的事件派发,可采用字符串拼接或参数组合的方式将事件派发到指定对象。
采用星型架构 + 事件机制
由于 Unity3D 没有明确的入口函数,不利于代码跟踪,采用星型架构 + 事件机制的基础架构可带来诸多便利。
利用界面扩展能力
Unity 的界面扩展能力强大,借助 CLR(Common Language Runtime)的反射能力,在 C# 中开发界面十分容易。
做好 Tag、Layer 规划
在规划 Tag 和 Layer 时,需考虑业务中不同物体之间的交互需求。
直观获取 Prefab 或 GameObject
在代码中获取某个 Prefab 或 GameObject 时,可通过界面拖放目标的方式,这样更加直观,能应对目标名称变化的情况,还可减少代码量。
代码方面的注意事项
编程语言选择思考
对于 C# 这种静态强类型面向对象语言,继承承担了代码复用和接口继承两个职责。虽然其性能比 Lua 略高,但在游戏开发中,由于性能瓶颈通常不在业务本身,设计问题更为突出。像 Lua 这种动态语言的元编程能更好地贯彻单点真理,使代码保持语义。静态强类型面向对象语言更适合需求稳定、严谨的系统开发,而游戏开发容易受到多次策划需求变更的影响,导致语义扭曲、抽象泄露和各种 hack 代码。
代码开发注意点
- 防止破解:Unity3D 发布版本的 IL 容易被反编译,因此需要考虑代码混淆,并注意混淆对编辑器的影响。
- 类型使用:复杂类型尽量使用引用类型,因为值类型反射麻烦,不利于序列化和编辑器开发。同时,要注意值类型赋值对象是否为临时对象。引用类型释放后,引用它的指针会置为 null,可放心使用。
- 慎用部分特性:foreach、linq、协程应谨慎使用,反射仅在编辑器中使用。
- 封装 Time:考虑封装 Time,方便实现暂停功能。
- 使用调度器:使用调度器完成功能,而非在 Update 中自行维护状态,这样便于实现暂停功能,使代码更清晰、功能更内聚。
- 增量更新规划:从项目开始就应规划好增量更新方案。
美术方面的要点
编辑器扩展与资源管理
Unity3D 可通过扩展编辑器让非技术人员参与界面编辑工作。要组织好美术资源的规格、路径,自动生成 Prefab。同时,规划好游戏场景物件的逻辑节点,通过编辑器扩展实现复杂功能,供策划人员进行微调,特别是在可视化要求较高的模块,如动作调整。
原型美术制作
制作原型美术可提高开发效率。
统一约定
制定统一的约定,如模型中心对齐、角色脚部对齐、统一缩放、统一动画骨骼命名和统一资源路径。
换装功能规划
从项目开始就应考虑好支持换装(avatar)的功能。
资源加载与优化
尽早规划资源加载和优化方案,虽然初期只需给出雏形,但这有助于把握需求。若未规划好异步加载和资源释放,可能会导致阻塞卡顿和内存飙升。合理的规划也为后续的代码修改提供了空间。