这个说来话长,先随便记录几条吧:
1、反向播放动画
当我们只有一个方向的动画,比如只有前进动画,我们又需要做一个后退的功能,可以在播放动画的时候设置Speed属性为-1,然后就会反向播放前进动画。
2、多Inspector窗口比较
在Unity开发的时候,有时需要调试对比两个类似的对象的数据,可以点击Inspector窗口右上角Lock按钮,然后新增标签页添加一个Inspector窗口,选中另一个游戏对象,就可以相互比较。
3、多场景编辑
在Hiberarchy窗口下面可以打开场景,可以把多场景的物体合并到一个场景上,这个功能可以在一定程度上做到场景切分编辑。
4、Unity自带编辑器
历经版本迭代,Unity最强大的应该是它的Editor,我们可以把编辑器扩展成一个我们想要的任意配置工具,如技能编辑器、人物属性编辑器等,也可以使用ScriptableObjects管理游戏配置数据,把这些数据序列化存储。
5、ALT + 鼠标左键点击 Hierarchy 对象可以展开和收起对象的所有子对象
6、依次点击 暂停 -> 播放 -> 下一步 按钮可以从第一次帧开始调试程序
7、用好 Asset Store 这个宝库,里面有很多免费插件可以增强 Unity 编辑器!
比如这款免费插件可以快速打开 Unity 的特殊文件夹:
8、创建透明的材质
a.Unity 创建并配置材质
在 Project 视图里,创建一个材质,并命名为 TransMaterial,选中它然后在 Inspector 视图里修改 Shader 属性为 Transparent/Diffuse,如图所示:
b.Unity 制作有透明效果的纹理
选择一张有趣的图片,本小节将在 PhotoShop 里处理这张图片,简单来说就是为此图片添加透明度的信息。示例图片如下:
(1)在通道窗口中,新建一个通道,使用默认的名称 Alpha 1。
(2)选中 RGB 通道,然后使用 PhotoShop 中的魔棒工具,圈选出图片的背景区域。再选中 Alpha 1 通道,此时背景的轮廓线在此通道下依然可见。使用油漆桶工具为背景轮廓填充黑色,如图所示:
记录的透明度信息是:动画角色完全不透明、其余完全透明。
(3)存储此文件,并导入 Unity 以供接下来的使用。
c. 创建透明的材质的效果展示
选中 Project 视图里的 TransMaterial,然后在 Inspector 视图里修改 Base(RGB)Trans(A) 属性为上一小节导入的纹理。接着在游戏场景中新建一个立方体,将 TransMaterial 材质拖动到此立方体对象上,在场景中就可以看出效果,如图所示,与一个没有使用透明材质的球体做了对比:
9、考虑把关卡保存为 XML,而非 scene
这是一种很奇妙的技术:
- 它可以让你不必每个场景都设置一遍;
- 他可以加载的更快(如果大多数对象都是在场景之间共享的)。
- 它让场景的版本合并变的简单(就算是 Unity 的新的文本格式的 Scene,也由于数据太多,而让版本合并变的不切实际)。
- 它可以使得在关卡之间保持数据更简便。
你仍就可以使用 Unity 作为关卡编辑器(尽管你用不着了)。你需要写一些你的数据的序列化和反序列化的代码,并实现在编辑器和游戏运行时加载关卡、在编辑器中保存关卡。你可能需要模仿 Unity 的 ID 系统来维护对象之间的引用关系。
10、使用 cookie 类型的纹理模拟云层的移动
现实生活中,当阳光直射大地,而天空中又有很多云时,云层的影子总是会投射在大地上,风吹着云层移动,影子也跟着运动,如图所示:
而在游戏中,模拟与之类似的大气现象时,就需要使用 cookie 类型的纹理
制作云层效果的纹理
在photoshop中完成的准备工作
本小节将使用 PhotoShop 绘制有云层效果的纹理图,然后为其添加透明度信息。具体操作过程如下:
a.使用 PhotoShop 创建 512×512 像素大小的图
b.在 PhotoShop 内,单击【滤镜】|【渲染】|【云彩】命令,即可在瞬间完成云层的绘制,如图所示:
c.全选(Ctrl+A)并复制(Ctrl+C)此图像,切换到通道窗口下,新建通道,使用默认的名称 Alpha 1,选中新建的通道,然后粘贴(Ctrl+V)。这样透明度的信息也就添加完了
d.存储此云层纹理,然后导入到 Unity
在 Unity 中完成的准备工作
为了模拟云层的移动效果,需要想游戏场景中添加相应对象,并做些简单设置,具体步骤如下:
(1)在 Project 视图里,选中导入的云层纹理,然后在 Inspector 视图里设置下列属性值,如图所示:
Texture Type 为 Cookie
Light Type 为 Directional
(2)单击 GameObject|Create Other|Terrain 和 Directional Light 命令,为游戏添加地形(Terrain)和方向光源(Directional Light)对象。
(3)选中 Directional Light,然后在 Inspector 视图里,修改光源下列属性,如图所示:
- Position 的 X、Y、Z 均设置为 0;
- Rotation 的 X、Y、Z 设置为 90、0、0;此时光线会与地形平面垂直,(为了避免阴影扭曲)如图所示:
- Cookie 设置为云层纹理
- Cookie Size 设置为 200;此属性控制照射在地形上的云层的密度,值越大密度越小
- Shadow Type 设置为 No Shadows
编写控制云层移动的脚本
光是将云层的阴影投射在地形平面上,还看不出什么效果,所以本小节打算编写一个脚本,用于控制云层的移动,这样的话效果会更好些。在 Project 视图下,创建一个 C#脚本,并命名为 MovingShadows。打开此脚本,写入下面的代码:
using UnityEngine; using System.Collections; public class MovingShadows : MonoBehaviour { public float windSpeedX; // 在 X 轴方向上的速度 public float windSpeedZ; // 在 z 轴方向上的速度 public float lightCookieSize; // 直线光源 Cookie Size 属性的值 private Vector3 initPos; // 脚本被初始化时,调用此函数 void Start () { initPos = transform.position; } // 运行游戏时,每帧都调用此函数 void Update () { // 在 X 轴方向,移动云层 if (Mathf.Abs(transform.position.x) >= Mathf.Abs(initPos.x) + lightCookieSize) { Vector3 pos = transform.position; pos.x = initPos.x; transform.position = pos; } else { transform.Translate(Time.deltaTime * windSpeedX, 0, 0, Space.World); } // 在 Z 轴方向,移动云层 if (Mathf.Abs(transform.position.z) >= Mathf.Abs(initPos.z) + lightCookieSize) { Vector3 pos = transform.position; pos.z = initPos.z; transform.position = pos; } else { transform.Translate(0, 0, Time.deltaTime * windSpeedZ,Space.World); } } }
此脚本将被赋予方向光源。游戏开始运行时,脚本 11 行的 Start() 函数被执行,获知当前方向光源的位置;游戏运行时,16 行的 Update() 在每帧都被执行的,作用是控制方向光源在 XZ 平面上的移动。
选中被赋予 MovingShadows 脚本的方向光源,在 Inspector 视图里可以看到脚本组件上的 3 个属性:Wind Speed X、Wind Speed Z 和 Light Cookie Size,如图所示:
云层效果展示
11、延迟销毁游戏对象
默认情况下,使用 Destroy () 方法会立即销毁游戏对象,如果想延迟一段时间再销毁,可在此方法中传递一个时间参数,如下:
Destroy(gameObject,2f);
12、脚本不挂载到游戏对象执行
通常情况下,新建的脚本要挂载到游戏对象上才能运行,如果在脚本中的方法前使用
[RuntimeInitializeOnLoadMethod (RuntimeInitializeLoadType.AfterSceneLoad)],可以不用挂载到任何游戏对象上即可在程序运行时执行此方法,方便在在程序初始化前做一些额外的初始化工作。如下代码所示:
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] public static void DoSomething() { Debug.Log("It's the start of the game"); }
13、协程嵌套
在一个协程里开启另外一个协程,可使用以下方法:
void Start() { StartCoroutine(FirstCo()); } IEnumerator FirstCo() { yield return StartCoroutine(SecondCo()); } IEnumerator SecondCo() { yield return 0; }
14、快速比较距离
将两点之间的距离与一个固定距离进行比较时,可使两点相减然后取平方(即 sqrMagnitude),然后用该值与某个距离值的平方进行比较。不建议使用 Vector3.Distance 方法获取两点之间距离,然后与给定的距离值进行比较。因为 Vector3.Distance (a,b) 相当于 (a-b).magnitude,即求平方后开根,而 sqrMagnitude 方法省去了求平方根的操作,所以比 magnitude 执行快。
建议:
if ((pointA - pointB).sqrMagnitude < dist * dist) { }
不建议:
if (Vector3.Distance(pointA, pointB) < dist) { }
15、使用空游戏对象作为分隔符
在 Hierarchy 面板中,可以使用名称中带有分隔符的空游戏对象进行组织管理。
16、绘制调试数据
当变量随着时间的推进而改变时,可使用 AnimationCurve 实例在程序运行时绘制此数据,如下代码所示:
public AnimationCurve plot = new AnimationCurve(); void Update() { float value = Mathf.Sin(Time.time); plot.AddKey(Time.realtimeSinceStartup, value); }
返回 Unity 编辑器,运行程序,点击 plot 属性,此时会随着时间动态绘制数据的变化情况,如下图所示:
17、模型优化
①减面:对场景模型减面优化是最常见的优化操作。主要是去掉对模型造型没有影响的面,用尽可能少的面数表达清楚模型的结构和造型。比如:物件非关节点及物件背面、内部不会看见的面删掉。
②合并模型:合并同一小范围内的非交互类的静态小物件,同时合并小物件的贴图。这样可以减少 DRAW CALL 的数量。如,一组不同大小的小草,一组大小形状不同的石头,一个书架和上面放置的很多书籍等。把这些小物件合并成一个 object,贴图也合成成一张贴图。高端手机平台上 draw call 一般控制在 300 左右。
③LOD:建筑和复杂的物件用 LOD 模型和远处剔除来减少同屏面数。地形的 LOD 系统也可以对地形的面数做很大的优化。
④模型的重复利用:相同的多个物件在 unity 内复制使用,复制的多个物体在引擎计算上算一个物体。但也不可复制太多个,太多会对内存带来很大压力。相同的物件太多,建议把几个合并成一组做为一个 Object,多做几组,再进行复制。参考②。
⑤地形优化:如果是用 unity 自带的地形工具制作的地形,可以用 T4M 插件转化成 T4M 格式地形,设置一个顶点值转化后可以对地形优化很多。T4M 也可以设置 lod 模型。
更新ing...