[Unity]手工Mesh合批
2019/12
30
21:12
public static class EditorCombineTool
{
const string CombineNodeName = "__COMBMESH__";
[MenuItem("GameObject/Tool/合批")]
static public void CombineTool()
{
if (Selection.activeGameObject == null)
{
Log.Error("没有选中的物件!");
return;
}
CombineObj(Selection.activeGameObject);
}
static public void CombineObj(GameObject rootObj)
{
int childCount = rootObj.transform.childCount;
for(int i=childCount-1; i>=0; i--)
{
if ( rootObj.transform.GetChild(i).name == CombineNodeName )
{
GameObject.DestroyImmediate( rootObj.transform.GetChild(i).gameObject );
}
}
Dictionary<long, List<GameObject>> matMap = new Dictionary<long, List<GameObject>>();
var mrs = rootObj.GetComponentsInChildren<MeshRenderer>();
if (mrs.Length == 0)
{
Log.Error("没有可操作的对象1!");
return;
}
for(int i=0; i<mrs.Length; ++i)
{
var mr = mrs[i];
if (mr.sharedMaterial == null)
{
continue;
}
int insId = mr.sharedMaterial.GetInstanceID();
var key = Long64.Make64(insId, mr.gameObject.layer);
List<GameObject> list;
if (!matMap.TryGetValue(key, out list))
{
list = new List<GameObject>();
matMap.Add(key, list);
}
list.Add( mr.gameObject );
}
if (matMap.Count == 0)
{
Log.Error("没有可操作的对象2!");
return;
}
List< List<GameObject> > comblist = new List<List<GameObject>> ();
foreach(var kv in matMap)
{
var gos = kv.Value;
if (gos.Count > 1)
{
comblist.Add(gos);
}
else
{
Log.Warning("单位过少,不合批:{0}", gos[0].GetFullPathName());
}
}
for(int i=0; i< comblist.Count;++i)
{
var newChild = new GameObject(CombineNodeName);
newChild.transform.SetParent(rootObj.transform, false);
var gos = comblist[i];
var oldMr = gos[0].GetComponent<MeshRenderer>();
if (oldMr == null)
{
Log.Error("老的材质出了问题! {0}", gos[0].GetFullPathName());
continue;
}
var newMf = newChild.AddComponent<MeshFilter>();
newMf.sharedMesh = CombineMeshRender(rootObj.name, rootObj, gos);
var newMr = newChild.AddComponent<MeshRenderer>();
newMr.sharedMaterial = oldMr.sharedMaterial;
foreach(var g in gos)
{
g.SetActive(false);
}
}
AssetDatabase.Refresh();
EditorSceneManager.MarkAllScenesDirty();
}
public static Mesh CombineMeshRender(string prefixName, GameObject rootObj, List<GameObject> input)
{
var matrix = rootObj.transform.worldToLocalMatrix;
CombineInstance[] combine = new CombineInstance[input.Count];
for(int i=0; i<input.Count; ++i)
{
var mf = input[i].GetComponent<MeshFilter>();
combine[i].mesh = mf.sharedMesh;
combine[i].transform = matrix * mf.transform.localToWorldMatrix;
}
Mesh mesh = new Mesh();
mesh.CombineMeshes(combine, true);
var number = string.Empty;
string assetPath = string.Empty;
for(int i=0; i<100; ++i)
{
number = Random.Range(100000, 900000).ToString();
assetPath = "Assets/Arts/CombineMesh/" + prefixName + "_"+ number + ".asset";
if (!System.IO.File.Exists(assetPath))
{
break;
}
}
AssetDatabase.CreateAsset(mesh , assetPath);
AssetDatabase.SaveAssets();
var meshRet = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Mesh)) as Mesh;
return meshRet;
}
}
CopyRights: The Post by BY-NC-SA For Authorization,Original If Not Noted,Reprint Please Indicate From 老刘@开发笔记
Post Link: [Unity]手工Mesh合批
Post Link: [Unity]手工Mesh合批