# 光照优化
减少不必要的光源的使用,调节好每个 Light 组件的属性,平衡视觉效果和游戏性能。
优先考虑使用烘焙光照或者混合光照,此时可以配合光照探针使用。Lighting 窗口可以设置烘焙光照的参数。减少启用的阴影投射。
根据摄像机距离光源的距离,用脚本来决定是否启用光源和阴影。但是这样就会花费一些性能来计算摄像机到光源的距离。
可以考虑设置光照的阴影。无阴影的性能最好,硬阴影的性能稍差,软阴影的视觉效果最好,但是性能是这三者中最差的。
- 备注:光照和阴影最影响项目的性能,其次才是模型网格和贴图。把实时光照改成烘焙光照,可以使游戏性能大幅度增加。
注意 MeshRenderer 组件上的属性,默认情况下,Unity 会启用阴影投射和接收、光照探针采样、反射探针采样和运动矢量计算。如果项目不需要这些功能中的一个或多个,请确保关闭它们。2D 游戏尤其要注意,往往都不需要它们。
远处的景物,如果确定玩家无法到达,则可以不用模型,而是把远处的景物做成一张贴图放到天空盒的材质中,给天空盒使用。也可以使用反射探针烘焙出一张贴图,然后放到天空盒的材质。
# 图片优化
如果这张图片是应用在移动端的,则 == 导入 Unity 前,可以对这张图的每条边进行调整,确保每条边的长度都是 2 的正整数次方个像素。== 例如 2、4、8、16...256、512、1024、2048、4096...。这个做法只对移动端有效。
图片导入 Unity 后,可以选中这张图片,在 Inspector 窗口设置它的属性。
- 设置这些属性,可以在发布不同的平台,分别对该图片进行相应的压缩。可以在合理的范围内减小 Max Size,对于许多移动端的游戏,2048x2048 或 1024x1024 足以满足纹理图集的要求,而 512x512 足以满足应用于 3D 模型的纹理的要求。
- 如果图片不需要读写,则可以取消勾选 Read/Write Enabled,如果勾选可能导致双倍的内存占用。
- Filter Mode 一般选择 Bilinear 即可平衡性能和视觉效果,如果选择 Point (no filter),则视觉效果不太行,但性能开销也小,如果选择 Trilinera,则视觉效果最好,但性能开销最大。Aniso Level 一般选择 1,只有个别比较重要的图片才需要设置为大于等于 2 的值。
图片导入 Unity 后,会默认生成 Mip Maps 格式。
- 当摄像机到这幅贴图距离近,则显示最原始的图片,当摄像机距离这幅贴图的距离远,则这幅贴图会变模糊,以此降低渲染的性能消耗。
- 但由于之前显示的一幅图,现在变成了有多幅,所以这样会略微增加内存消耗。如果确定本游戏的摄像机到图片的距离几乎不怎么变化,则可以禁用这个功能。点击该贴图,在 Inspector 面板的 Advanced 中取消勾选 Generate Mip Maps,这样就不会生成 Mip Maps,增加游戏性能。
- 如果是 2D 游戏则可以禁用这个功能。如果是 UI 贴图,也可以禁用这个功能。
图片导入 Unity 后,可以选中这张图片,在 Inspector 窗口设置它在各个平台的 Format 和 Compressor Quality。Format 可以参考官方文档:https://docs.unity3d.com/2021.3/Documentation/Manual/class-TextureImporterOverride.html
用 Sprite Atlas 把图片打包成图集。但是这样一来,要使用图集中的任意一张图片,都会先加载这整个图集,这样占用的内存会增加。
Sprite Atlas 的优点
- 减小资源文件所占的大小
- 打包到同一个 Sprite Atlas 图集中的图片会共享相同的纹理数据,减少了重复的存储,往往能起到优化内存的作用
- 可以减少 DrawCall,提高游戏的渲染性能
Sprite Atlas 的缺点
- 需要手动将图片添加到 Sprite Atlas,增加了额外的工作量
- 当加载图集中的任意一张图,都会先加载整个图集。如果把一些不常用的图打包到同一个图集中,则会浪费内存
在代码中控制加载 Sprite Atlas
void Awake() | |
{ | |
spriteAtlas = Resources.Load<SpriteAtlas>("MySpriteAtlas"); | |
} | |
void Update() | |
{ | |
if (Input.GetKeyDown(KeyCode.Q)) | |
{ | |
image1.sprite = spriteAtlas.GetSprite("trees_0"); | |
} | |
if (Input.GetKeyDown(KeyCode.W)) | |
{ | |
image2.sprite = spriteAtlas.GetSprite("trees_1"); | |
} | |
} |