Unity中游戏包体过大,运行卡的优化方式总结

在游戏中的DrawCall越大,游戏性能消耗越大。而在我们2018.4.1中,可以在stats中看到Batches数量   它和DrawCall都是性能消耗显示的参数,当游戏中的模型越多,DrawCall和Batches的数量越大,而优化是降低DrawCall和Batches。

 优化方式也分为很多种:
                资源优化(模型,声音,贴图)
              (GPU)渲染优化:
                    1.LOD(层级细节)
                    2.OcclusionCulling遮挡剔除
                    3.LightMap光照贴图
                    4.Mesh合并
                代码优化

Unity中游戏包体过大,运行卡的优化方式总结_第1张图片
Unity中游戏包体过大,运行卡的优化方式总结_第2张图片

资源优化:

1.模型优化(Mesh)
I.动态模型:面片数<3000、材质数<3、骨骼数<50.
II.静态模型:顶点数<500
(这标准不是唯一标准,视游戏而定)
2.音乐
I.长时间音乐:如背景音乐,建议使用压缩格式.mp3->(LoadType:Compressed In Memory)
II.短时间音乐:建议使用非压缩格式.wav->(LoadType:Decompress On Load)
3.贴图
I.Texture:都去掉alpha通道,作为背景展示的图片,基本都没有透明要求。
II.Loading图这类需要比较精细的,则把图片设置为Automatic TrueColor,设置真彩色,保证不失真
III.地图、缩略图、UI背景图等等要求不精细的,则可以设置为自动压缩格式(有压缩情况,可以在Advance里面设置toNearest)
IIII.图片尽量打包成图集,(图片大小<1024)。

GPU渲染优化

1.LOD层级细节: 当视野离模型比较远的时候用粗糙的模型,当视野离模型最近的时候用精细的模型。
实现方法:在场景中创建一个空物体,然后添加LOD Group组件,依次把最精细到粗糙的模型拉到LOD0-LOD3中.
Unity中游戏包体过大,运行卡的优化方式总结_第3张图片
视野拉近模型显示最精细,视野拉远模型显示最粗糙。
Unity中游戏包体过大,运行卡的优化方式总结_第4张图片
2.遮挡剔除: 只会渲染在视野内的模型,而在视野外的模型则会剔除。
实现方法:选中要遮挡剔除的物体,static ---->Occluder static ,然后打开Window—>Rendering----->OcclusionCulling---->break。会生成一个遮挡剔除的文件:随着摄像机视野的拉近,视野外的物体就被剔除了。

Unity中游戏包体过大,运行卡的优化方式总结_第5张图片
Unity中游戏包体过大,运行卡的优化方式总结_第6张图片

做遮挡剔除之前的Drawcall数量和Batches:
Unity中游戏包体过大,运行卡的优化方式总结_第7张图片
做遮挡剔除后随着摄像机视野拉近DrawCall数量和Batcher依次在减少:
Unity中游戏包体过大,运行卡的优化方式总结_第8张图片
3.光照贴图: 把场景中的大量光源烘焙成贴图。
实现方法:选中被光源照着的物体,static----->LightMap。 选中光源,把Model------->baked。点击Window------>Reading-------->Lighting Settings----->取消勾选 Auto Generate ----->点击 Generate Lighting.把光源删除,发现光照效果还存在,DrawCall和Batches比之前少了很多。
Unity中游戏包体过大,运行卡的优化方式总结_第9张图片
4.Mesh合并:把多个模型的Mesh合并成一个,合并可以在3Dmax中完成也可以在Unity中完成。
实现方法:使用代码进行合并。

// 合并的代码
  void Test()
    {
        MeshFilter[] filters = GetComponentsInChildren<MeshFilter>();

        CombineInstance[] combiners = new CombineInstance[filters.Length];

        for(int i = 0; i < filters.Length; i++)
        {
            combiners[i].mesh = filters[i].sharedMesh;
            combiners[i].transform = filters[i].transform.localToWorldMatrix;
        }

        Mesh finalMesh = new Mesh();
        finalMesh.CombineMeshes(combiners);

        GetComponent<MeshFilter>().sharedMesh = finalMesh;
    }

官方提供的动态批处理:
Unity中游戏包体过大,运行卡的优化方式总结_第10张图片

代码优化

对象池:预先生成一部分物体SetActive为false,放到集合或者字典中,使用时设置位置和SetActive为true就行。这里放一下对象池代码:

public class ObjectPool : MonoBehaviour
{
 //单例模式
 public static ObjectPool instance;

 //字典里的String就是坑的名字,每一个坑对应一个GameObject列表  
 Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>() { };

 private void Awake()
 {
     instance = this;
 }

 public GameObject GetPool(GameObject go, Vector3 position)
 {
     string key = go.name + "(Clone)";//要去拿东西的坑名字  

     GameObject rongqi; //你用来取物体的容器;  
     //下面分三种情况来分析  
     if (pool.ContainsKey(key) && pool[key].Count > 0)//如果坑存在,坑里有东西  
     {
         //直接拿走坑里面的第一个  
         rongqi = pool[key][0];
         pool[key].RemoveAt(0);//把第一个位置释放;  
     }
     else if (pool.ContainsKey(key) && pool[key].Count <= 0)//坑存在,坑里没东西  
     {
         //那就直接初始化一个吧  
         rongqi = Instantiate(go, position, Quaternion.identity) as GameObject;
     }
     else  //没坑  
     {
         //不仅要初始化,还要把坑加上  
         rongqi = Instantiate(go, position, Quaternion.identity) as GameObject;
         pool.Add(key, new List<GameObject>() { });
     }

     //调整物体初始状态  
     rongqi.SetActive(true);

     //这里加了一个子物体也显示的代码  可以根据自己需要去调整
     foreach (Transform child in rongqi.transform)
     {
        child.gameObject.SetActive(true);
     }

     //位置初始化  
     rongqi.transform.position = position;
     return rongqi;
 }
 //放入池子中的方法  
 public void AddPool(GameObject go)
 {
     string key = go.name;
     pool[key].Add(go);
     go.SetActive(false);
 }
}

好了就介绍到这里了!

你可能感兴趣的:(优化,包体过大,卡顿)