脚本编译规则
- 最终所有代码都会生成 dll,放在 Project/Library/ScriptAssembiles 下面。
- 脚本分为运行时和编辑时两类,运行时脚本最终会编译进游戏包中,而编辑时脚本仅用于编辑器模式下,不会被打包进游戏包。
- 脚本编译顺序:最先编译 Plugins 目录下的,然后是 Plugins 下的所有 Editor 子目录,然后编译其他目录,最后编译其他 Editor 目录。
- 先编译的不可以访问后面的数据,所以 Plugins 下的代码不能访问其他代码,后编译的可以访问先编译的脚本。
- 各目录脚本最终所在的 dll:
- Plugins 下非 Editor 目录脚本编译进 Assembly-CSharp-firstpass.dll
- Plugins 下的 Editor 目录脚本编译进 Assembly-CSharp-Editor-firstpass.dll
- 其他非 Editor 目录脚本编译进 Assembly-CSharp.dll
- 其他 Editor 目录脚本编译进 Assembly-CSharp-Editor.dll
优化编译
Tips:
- 当游戏内有很多 C# 代码时,改动一点点代码就需要等很久,因为 Unity 在重新编译 dll,可以将代码分为框架类代码和逻辑性代码,框架性代码一般写好之后不会经常变动,常常需要更改的往往是逻辑性代码,将框架性代码放到 Plugins 目录下,那么在修改逻辑性代码时,就不会额外的编译 Plugins 目录下的代码了。
- 如果代码量非常巨大,那么编译还是会很慢,可以将部分 CS 代码预先变异成 dll,这样编译速度就更快了。(暂时还不知道怎么做,先记录一下)
编译DLL (没懂)
.NET 可以把 C/C++ 语言编译进 DLL,但是游戏发布后,有的平台是识别不了的,例如移动平台,此时如果编译 DLL 时只能编译 C# 代码,则需要在 macOS 系统中打开终端,输入编译指令,DLL 编译完后直接拖到项目中即可。
1 | mcs -r:/Applications/Unity/Unity.app/Contents/Managed/UnityEngine.dll |
- UnityEngine.dll:编译所依赖的 DLL 文件。
- -target:library:生成 Library1 类型。
- -out:test.dll:最终生成 DLL 的保存目录。
- *.cs:表示当前目录下的所有 C# 代码。如果有多个目录多个文件,可以用空格分隔。
脚本跨平台
雨松大大夸了一波 Unity 的跨平台,没懂,应该是指 Unity 针对每个平台有一套底层的核心库,然后通过 C# 去调用,所以对于用户来说只需要使用 C# 就好了。
Unity 自己提供了两个核心的 DLL 库,Unity 编辑器只支持 Windows、macOS 和 Linux 这 3 个平台,所以代码大部分是由 C# 编写的并且编译在 UnityEditor.dll 中,然后通过 Mono 实现了跨平台。运行时由于它兼容的平台非常多(目前已经有 20 多个平台了),并不是所有平台都能运行 DLL 的。再说,底层渲染方法也不能使用 C# 来调用,所以 Unity 只把 C# 接口封装到了 UnityEngine.dll 中。至于更底层的内部实现,则是由这个 DLL 再去调用 C++ 来完成的。拿移动平台来说,编译 C++ 的方式是不同的,Android 需要编译成 .so,ios 则需要编译在 .a 中。所以,Unity 会针对每个平台编译出这份核心库,从而实现了跨平台。现在 Unity 还支持 IL2CPP,它可以把 DLL 代码转化成 C++ 来执行,这从效率上又能提高一个台阶,并且开发者依然使用 C#,只有在打包的时候才会转化成 IL2CPP,整个过程使开发者无感,超棒der。虽然拿不到 Unity 的源码,但是 UnityEngine.dll 和 UnityEditor.dll 这两个 DLL 文件是可以反编译的。
程序集定义
上面提过如果程序过大的话,那么每次改动一点都会等待很久重新编译,除了上面两种方法之外还可以使用程序集。
用户在一个文件夹下新建一个程序集定义,那么就意味着这个文件夹及其子文件夹都变成了一个程序集,单独编译成一个 DLL,如果需要依赖其他的程序集的话,在程序集定义的 Inspector 面板上设置依赖。如图是在 A 程序集中设置了对 B 程序集的依赖。
日志
在游戏发布时一定要将 Debug 给关掉,因为他会有额外的消耗,或者在编写需要输出日志的时候就加上,如果没有定义 UNITY_EDITOR 那么就关闭日志。
1 |
|
除此之外,错误日志并不是主动打的,下面实现将错误信息打在屏幕上的功能,以方便 Debug。
1 | // 文件名:Script_04_21.cs |
在代码中我们估计打印了一个错误和故意搞了一个异常,运行效果如图所示,错误信息和调用栈都被打印下来了。
脚本调试
Unity 2018 彻底废除了 MonoDevelop,使用 VS,设置了断点之后,在点击 “附加到 Unity”,就会在断点处停住,但不知道为什么我无法像书上所说的,直接将鼠标放到变量身上就可以看到对应的值。
书中还写了一个小技巧,可以直接在监视中直接输入 gameObject.transfrom.position
或者 gameObject.name
来直接查看。