原文链接 http://devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/
Tips
- 避免分歧资源拷贝或备份资源使用 __ 等明显标志
- 保留版本副本
- 考虑使用额外工具编辑?
- 考虑使用XML格式存储关卡(AssetBundles?)
- 编写通用检查代码
- 使用空GameObject作为目录
不要将mesh作为脚本的根组件可使用空gameobject - 放置维护资源或目录于(0,0,0)坐标
- 尽量减少GUI偏移量
- world_floor_y=0
- 保证每个子场景scene可单独运行方便调试
- 人物(或站立的object)轴放置于底部
- 所有mesh的正面面向±z轴
- scale初始即正确
- 制作一个用于GUI组件和手动创建粒子的双多边形平面?
- 美术测试
- 万物皆prefab方便更改属性,方便调试,场景运行时也可保存更改
- 将特例化的物件包装为prefab而不是实例例两个enemy仅属性不同,一个prefab
- 链接prefab而不是实例将prefab拖动到场景时链接的实例将失效
- 尽可能在实例间自动建立链接程序化建立实例之间的链接关系
- 使用安全的流程分支prefab(备份)
- 扩建自用mono behaviour作为所有组件的base?
- 为Invoke,协程,实例化定义安全方法
- 使用扩展与共享接口的组件一起工作?
- 添加扩展使语法更方便
- 安全getcomponents
T GetSafeComponent<T>(this GameObject obj) where T : MonoBehaviour {
T comp = obj.GetComponent<T>();
if(comp == null) {
Debug.LogError("GetSafeComponent "+typeof(T)+" is null",obj);
}
return comp;
}
- 同一件事避免使用不同的常用名
- 维护自己的Time类?
- 不要让clone物件打乱层级结构
- 使用单例模式
- 当你不想编辑窗口改变变量时不要用public(使用[HideInspector])
- 从游戏逻辑中分离接口函数接口(组件独立化 功能细分)
- 分离状态和记录???bookkeeping
- 分离专业化配置(模板 子类)
public class EnemyTemplate {
...
}
public class WeakEnemyTemplate : EnemyTemplate {
...
}
public class StrongEnemyTemplate : EnemyTemplate {
...
}
public class Enemy <TemplateType> where TemplateType : EnemyTemplate {
TemplateType enemy;
...
}
public class WeakEnemy : Enemy <WeakEnemyTemplate> {
...
}
public class StrongEnemy : Enemy <StrongEnemyTemplate> {
...
}
- 除了显示文本 不要使用字符串
- 避免使用公共索引耦合的数组
//代码没问题 但是不便于管理
currentWeaponIndex = index;
SwitchWeapon(weapons[currentWeapon]);
Fire(bullets[currentWeapon]);
FireParticles(particles[currentWeapon]);
//封装
public class Weapon
{
public GameObject prefab;
public ParticleSystem particles;
public Bullet bullet;
}
- 避免将数组用于序列以外的结构
- 将数据序列化分装到类中使编辑窗口看起来更整洁
- 如果有大量文本,将文本存入文件中
- ?
- 实现图形化工具调试物理 动画 AI
- 实现一个HTML日志记录器
- 实现一个fps记录器
- 实现屏幕快照快捷方式
- 实现打印玩家位置信息快捷方式
- 实现调试选项
- 略
- 维护一个拥有所有组件的场景
- 调试快捷键
- 记录更新
- 遵循文档命名规范和结构格式
优化
- 缓存组件
#if 0
void Update() {
//每次调用都会getcomponent<transform>()
transform.Translate(0, 0, 5);
}
#else
//缓存component
Transform thisTransform;
public new Transform transform {
get {
if (thisTransform == null) {
thisTransform = base.transform;
return thisTransform;
}
}
void Update() {
transform.Translate(0, 0, 5);
}
#endif
- 使用内置变量
eg. Vector.zero - 不需要时可禁用组件物体
eg. 使用Trigger控制组件开关 - 使用 enum.GetName() 代替 enum.ToString()
- 类型转换时,使用 as type 代替以类型作为前缀
- 不使用 GameObject.Find 而是使用一个 SerializeField 并将组件拖动到相应位置上
- 使用 OnBecameVisible 和 OnBecameInvisible
- 不要抛出异常(发布代码中)
- foreach导致内存泄漏(Unity5.5 Mono4.4 修复)
- 动态创建texture或mesh标记HideFlags.DontSave
- Debug.Break() 调试时关键帧暂停游戏
- 避免使用string
- 使用struct(栈区)
- 用结构体替换范围绑定的固定大小数组
- 避免使用IEnumerable扩展方法
- 尽量少使用函数指针
- 小心材质拷贝 使用myRenderer.sharedMaterial获取材质(如果不进行改动的化)