初步了解
什么是DrawCall?
在unity中,每次CPU准备数据并通知GPU的过程就称之为一个DrawCall。
具体过程就是:设置颜色-->绘图方式-->顶点坐标-->绘制-->结束,所以在绘制过程中,如果能在一次DrawCall完成所有绘制就会大大提高运行效率,进而达到优化的目的。
参考文章Unity优化之减少Drawcall_unity降低drawcall-CSDN博客
合并网格时候合并材质球 减少Draw Call
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class MergingMesh : Singleton<MergingMesh>
{
/// <summary>
/// 换装
/// </summary>
public void ChangeClother(RoleData roleData, GameObject target)
{
Dictionary<string, Transform> dic = new Dictionary<string, Transform>(); //字典存放自己的骨骼
Transform[] mybone = target.GetComponentsInChildren<Transform>(); //自身的骨骼 初始化
foreach (var item in mybone)
{
dic.Add(item.name, item);//添加自身骨骼
}
SkinnedMeshRenderer sk = target.AddComponent<SkinnedMeshRenderer>(); //动态蒙皮
//合并网格
#region 初始化身体
List<GameObject> bodys = new List<GameObject>();
bodys.Add(Resources.Load<GameObject>(roleData.tou));
bodys.Add(Resources.Load<GameObject>(roleData.yifu));
bodys.Add(Resources.Load<GameObject>(roleData.tui));
#endregion
Mesh mesh = new Mesh(); //网格
List<Vector2> uvs = new List<Vector2>();//uvs
List<Transform> bones = new List<Transform>();//自身骨骼
Texture2D texture2D = new Texture2D(1024, 1024); //纹理
List<Texture2D> texture2Ds = new List<Texture2D>(); //存放身体 的纹理
for (int i = 0; i < bodys.Count; i++)
{
texture2Ds.Add(bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.mainTexture as Texture2D);//获得自身的纹理
}
Rect[] rects = texture2D.PackTextures(texture2Ds.ToArray(), 0); //矩阵 合并纹理
List<CombineInstance> combineInstances = new List<CombineInstance>(); //合并
for (int i = 0; i < bodys.Count; i++)
{
Transform[] bodybone = bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().bones; //所有的骨骼
foreach (var item in bodybone)
{
if (dic.ContainsKey(item.name))
{
bones.Add(dic[item.name]); //骨骼添加
}
}
//计算合并图片后的uv坐标
Mesh temp = bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh;
for (int j = 0; j < temp.uv.Length; j++)
{
uvs.Add(new Vector2(rects[i].x + rects[i].width * temp.uv[j].x, rects[i].y + rects[i].height * temp.uv[j].y));//添加uv
//矩阵和身体的x 加上 宽度 * 自身的uvx
}
CombineInstance combineInstance = new CombineInstance();
combineInstance.mesh = temp;
//combineInstance.transform = bodys[i].GetComponent<MeshFilter>().transform.localToWorldMatrix;//矩阵,用于在组合前变换网格
combineInstances.Add(combineInstance);
}
texture2D.Apply();
mesh.CombineMeshes(combineInstances.ToArray(), true, false); //合并mesh 第一个记得是 true 第二个 是 fase
mesh.uv = uvs.ToArray();//uv
MeshUtility.Optimize(mesh);//优化清除多余的顶点
sk.sharedMesh = mesh; //赋值
sk.bones = bones.ToArray();
Material material = new Material(Shader.Find("CarToonQ")); //生成材质球
Texture2D face = bodys[0].GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.GetTexture("_FaceTex") as Texture2D; //脸部纹理 第一个身体集合 是头部
material.SetTexture("_FaceTex", face);//给当前shader设置纹理
material.SetTexture("_MainTex", texture2D);
material.SetFloat ("_ScaleX",texture2D.width/face.width);//设置缩放比
material.SetFloat("_ScaleY", texture2D.height / face.width);
sk.sharedMaterial = material;
}
}