Unity 项目注意点总结 (持续更新)

编程中关于继承和接口的选择

  1. 当单纯需要代码复用时可使用继承, 但不允许使用 override
  2. 当明确存在默认行为时可使用继承以及 override
  3. 多态一律使用接口实现: interface

Unity 项目的中前期使用 Mono 打包, 后期使用 IL2CPP 打包

IL2CPP 打包需要安装的环境

IL2CPP打包环境

  1. Visual Studio 核心编辑器
  2. C++ 桌面开发环境
  3. MSVC C++ 编译器
  4. Windows 10 SDK / Windows 11 SDK

Unity 中使用 foreach 遍历不会有 GC

将函数作为参数时必须使用匿名方式且必须不发生闭包

直接传递函数的情况必然会有 GC, 无论传递的函数是否为静态函数

1
2
3
4
5
6
7
// 传递普通方法 Sum, 会有 GC
Launch(Sum);
private void Sum() { }

// 传递静态方法 Sum, 同样有 GC
Launch(Sum);
private static void Sum() { }

使用匿名方式传递函数, 则根据是否闭包决定有无 GC

1
2
3
4
5
6
7
8
9
10
11
12
13
// Sum 是闭包, 会有 GC
Launch(() => Sum());
private void Sum()
{
sum++;
}

// Sum 不是闭包, 无 GC
Launch(() => Sum());
private static void Sum()
{
sum++;
}

Unity 的 Git 仓库必须添加 RenameLimit 限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[user]
name = Kuroha
email = KurohaKirito@gmail.com
[diff]
renameLimit=1
renames=false
[merge]
renameLimit=1
renames=false
directoryRenames=conflict
[status]
renameLimit=1
renames=false
[http]
proxy = http://127.0.0.1:20122
[https]
proxy = https://127.0.0.1:20122

Unity 的 Git 仓库必须添加 .gitattribute 配置

https://github.com/gitattributes/gitattributes

Unity 项目所在电脑必须设置开启 "Unicode UTF-8 提供全球语言支持" 或者不要使用任何非 ASCII 字符

Unicode UTF8 提供全球语言支持

编程时 struct 内的字段必须是纯值类型, 如果含有引用类型, 请使用 class

  1. struct 中的字段禁止使用引用类型
  2. 当一个数据体内部的全部字段是一个不可变化的整体时, 才能使用 struct, 并且每一个 struct 都是一个独立的数据副本

性能优化时, 顶点数小于 300 的网格禁止参与静态批处理

当小于 300 定点数的网格参与静态批处理时, 即使它仅仅作为一个 submesh 存在, 但会导致整个静态网格的 KeepVertices 被开启, 导致顶点信息被保留在内存中, 从而使整个网格的内存占用翻倍

编程中关于 Null 值的处理

返回值

最终优化为: 项目中不存在任何的 return null 语句

优化措施:

  1. 对于值类型的返回值, 将合法的 return null 全部改为有效空白值, 比如 string.Empty, 0, -1 等
  2. 对于引用类型的返回值, 将合法的 return null 全部改为 out 类型参数返回, 本来的返回值改为 bool
  3. 任意类型的非法的 return null 全部删除, 改为输出错误日志并抛出异常

参数

  1. 使用 debug 断言进行判断, 断言的好处是 release 版本中断言是不执行的. 因此只要在 debug 版本中进行全覆盖测试, 就可以直接在 debug 版本中就杜绝参数为 null 的情况

最终结论

编程时任何方法只能返回 Task void bool string 这几种类型, 其中 string 是错误信息, bool 是成功标志