Unity优化之 draw call 有关的参数
Unity 优化(一) ------ 优化前了解以及方向
FPS:画面每秒传输帧数,,要避免动作不流畅的最低是 30;值越大性能越好
CPU:计算每帧需要消耗的时间,值越低说明计算越快,值越小性能越好
Batches:将某些 DrawCalls 合并,数量为合并后 DrawCall 的数量。
Tris:三角面
Verts:顶点
SetPass call:Shader 中 CPU 每次运行 Pass 之前都会产生一个 SetPass call。
Unity 优化(二) ------ 资源优化
长时间音乐使用 Mp3 格式(使用压缩格式),例如:背景音乐等
短时间音乐使用 wav 格式(不使用压缩格式),例如:音效
减少冗余资源和重复资源
A、Resources 目录下的资源不管是否被引用,都会打包进安装包
不使用的资源不要放在 Resources 目录下
B、不同目录下的相同资源文件,如果都被引用,那么都会打包进资源包,造成冗余
保证同一个资源文件在项目中只存放在一个目录位置
资源优化:使用 UWA 工具
渲染优化(GPU)和代码优化(CPU)
GPU:包括场景渲染和灯光处理等
CPU:数值计算
LOD——层级
当模型离视野近时,显示比较精细的模型,离视野比较远时显示比较粗糙的模型。
实现方法:
新建一个空物体,添加 LOD Group 组件,将模型拖进精细度按下图提示拖进对应位置,可根据实际情况调节每个 LOD 的占比。
遮挡剔除:降低 DrawCall
原理:在摄像机视野内的物体显示,在视野外的物体不显示。
实现方法:
(1)在场景中创建很多物体(方便观察)。全选中—点击 Static—Occluder Static
(2)点击 Windows—Occlusion Culling
(3)选择指定相机用于遮挡剔除计算
光照贴图:降低 Batches
实现方法:
(1)搭建好场景,选中场景中所有需要被光照的物体—点击 Static—LightmapStatic
(2)点击 Windowa—Lighting—Settings
(3)选择需要被烘焙的光源,将模式选择烘焙模式
(4)Scene—取消勾选—Generate Lighting
(5)选择烘焙后,下方是烘焙进度
(6)选择所有被烘焙的光源,取消 Light 勾选
这时还能看见光照效果,这时因为使用烘焙,生成了光照贴图
注意:如果觉得光照强度过强,在(4)前可修改
Light 组件中 Indensity 值,值越低,光照越暗
合并 Mesh:要求合并的 mesh 使用相同的材质。
实现方法:
(1)创建一个空物体 MeshCombine,并为其创建几个子物体,子物体层级任意
(2)新建脚本并挂在到(1)中的空物体 MeshCombine 上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshCombine : MonoBehaviour {
// Use this for initialization
void Start () {
CombineMesh();
}
void CombineMesh()
{
MeshFilter[] filters = GetComponentsInChildren<MeshFilter>();//获取空物体下所有子物体的MeshFilter组件并保存为一个数组
CombineInstance[] combiners = new CombineInstance[filters.Length];//unity提供的一个类,用于处理合并的实例
//将filters的一些属性设置給combiners
for (int i = 0; i < combiners.Length; i++)
{
combiners[i].mesh = filters[i].sharedMesh;
combiners[i].transform = filters[i].transform.localToWorldMatrix;//这里的transform不是一个组件而是一个矩阵转换,用于世界坐标与局部坐标之间的转换
}
Mesh finalMesh = new Mesh();
finalMesh.CombineMeshes(combiners);//合并mesh
GetComponent<MeshFilter>().sharedMesh = finalMesh;//将合并后的Mesh赋值到父物体上
}
}
(3)为(1)中的空物体 MeshCombine 添加两个组件:
MeshRender 组件:负责渲染
MeshFilter 组件:用于存放合并后的 mesh
并未 MeshRender 组件选择一个需要的材质。
(4)游戏运行,会将 MeshCombine 下的所有子物体中的 Mesh 合并并赋值到 MeshCombine 物体上,因此场景中将会出现两个一模一样的 mesh,这时在游戏运行时可直接删除其下的子物体,这时可明显看见 Batches 减少。
ObjectPool
对象池的使用可以说是非常常见。直接上代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoBehaviour {
public int objCount=5;//对象池中该类对象初始生成的个数
public GameObject buttlePreb;//需要实例化的预制
private List<GameObject> poolList = new List<GameObject>();//存放对象
void Start () {
InitPool();
}
//初始化对象池
void InitPool()
{
for (int i = 0; i < objCount; i++)
{
GameObject go = Instantiate(buttlePreb);//实例化对象
poolList.Add(go);//将实例化的对象添加到对象次
go.SetActive(false);//设置为隐藏—即未被使用
}
}
//从对象池中取对象
public GameObject ShowObj()
{
foreach (GameObject go in poolList)
{
if (!go.activeInHierarchy)
{
go.SetActive(true);
return go;
}
}
return null;
}
//使用协程,使得对象生成后等待指定时间隐藏—即放回对象池
public IEnumerator HideObj(GameObject go)
{
yield return new WaitForSeconds(3);
go.SetActive(false);
}
}
使用对象池:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class startBuntle : MonoBehaviour {
private ObjectPool objPool;
void Start () {
objPool = GetComponent<ObjectPool>();
}
void Update () {
if (Input.GetKeyUp(KeyCode.K))
{
GameObject go = objPool.ShowObj();
if (go != null)
{
//对象次还有可用对象
go.GetComponent<Rigidbody>().velocity = transform.forward * 30;
StartCoroutine(objPool.HideObj(go));
}
}
}
}
标题:Unity优化之 draw call 有关的参数
作者:shirln
地址:https://www.mmzsblog.cn/articles/2019/08/29/1567085834529.html
如未加特殊说明,文章均为原创,转载必须注明出处。均采用CC BY-SA 4.0 协议!
本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。若本站转载文章遗漏了原文链接,请及时告知,我们将做删除处理!文章观点不代表本网站立场,如需处理请联系首页客服。• 网站转载须在文章起始位置标注作者及原文连接,否则保留追究法律责任的权利。
• 公众号转载请联系网站首页的微信号申请白名单!
