{"id":864,"date":"2019-12-30T21:21:43","date_gmt":"2019-12-30T13:21:43","guid":{"rendered":"http:\/\/blog.coolcoding.cn\/?p=864"},"modified":"2020-09-27T17:03:14","modified_gmt":"2020-09-27T09:03:14","slug":"unity%e8%87%aa%e5%8a%a8%e5%90%88%e6%89%b9","status":"publish","type":"post","link":"https:\/\/blog.coolcoding.cn\/?p=864","title":{"rendered":"[Unity]\u624b\u5de5Mesh\u5408\u6279"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>public static class EditorCombineTool\n{\n    const string CombineNodeName = \"__COMBMESH__\";\n\n    [MenuItem(\"GameObject\/Tool\/\u5408\u6279\")]\n    static public void CombineTool()\n    {\n        if (Selection.activeGameObject == null)\n        {\n            Log.Error(\"\u6ca1\u6709\u9009\u4e2d\u7684\u7269\u4ef6!\");\n            return;\n        }\n\n        CombineObj(Selection.activeGameObject);\n    }\n\n    static public void CombineObj(GameObject rootObj)\n    {\n        int childCount = rootObj.transform.childCount;\n        for(int i=childCount-1; i>=0; i--)\n        {\n            if ( rootObj.transform.GetChild(i).name == CombineNodeName )\n            {\n                GameObject.DestroyImmediate( rootObj.transform.GetChild(i).gameObject );\n            }\n        }\n\n        Dictionary&lt;long, List&lt;GameObject>> matMap = new Dictionary&lt;long, List&lt;GameObject>>();\n\n        var mrs = rootObj.GetComponentsInChildren&lt;MeshRenderer>();\n        if (mrs.Length == 0)\n        {            \n            Log.Error(\"\u6ca1\u6709\u53ef\u64cd\u4f5c\u7684\u5bf9\u8c611\uff01\");\n            return;            \n        }\n        for(int i=0; i&lt;mrs.Length; ++i)\n        {\n            var mr = mrs[i];\n\n            if (mr.sharedMaterial == null)\n            {\n                continue;\n            }\n\n            int insId = mr.sharedMaterial.GetInstanceID();\n            var key = Long64.Make64(insId, mr.gameObject.layer);\n\n            List&lt;GameObject> list;\n            if (!matMap.TryGetValue(key, out list))\n            {\n                list = new List&lt;GameObject>();\n                matMap.Add(key, list);\n            }\n            list.Add( mr.gameObject );\n        }\n\n        if (matMap.Count == 0)\n        {\n            Log.Error(\"\u6ca1\u6709\u53ef\u64cd\u4f5c\u7684\u5bf9\u8c612\uff01\");\n            return;\n        }\n\n        List&lt; List&lt;GameObject> > comblist = new List&lt;List&lt;GameObject>> ();\n        foreach(var kv in matMap)\n        {\n            var gos = kv.Value;\n            if (gos.Count > 1)\n            {\n                comblist.Add(gos);\n            }\n            else\n            {\n                Log.Warning(\"\u5355\u4f4d\u8fc7\u5c11\uff0c\u4e0d\u5408\u6279\uff1a{0}\", gos[0].GetFullPathName());\n            }\n        }\n        \n        for(int i=0; i&lt; comblist.Count;++i)\n        {\n            var newChild = new GameObject(CombineNodeName);\n            newChild.transform.SetParent(rootObj.transform, false);\n            var gos = comblist[i];\n        \n            var oldMr = gos[0].GetComponent&lt;MeshRenderer>();\n            if (oldMr == null)\n            {\n                Log.Error(\"\u8001\u7684\u6750\u8d28\u51fa\u4e86\u95ee\u9898! {0}\", gos[0].GetFullPathName());\n                continue;\n            }\n\n            var newMf = newChild.AddComponent&lt;MeshFilter>();\n            newMf.sharedMesh = CombineMeshRender(rootObj.name, rootObj, gos);\n\n            var newMr = newChild.AddComponent&lt;MeshRenderer>();\n            newMr.sharedMaterial = oldMr.sharedMaterial;\n\n            foreach(var g in gos)\n            {\n                g.SetActive(false);\n            }\n        }       \n\n        AssetDatabase.Refresh();\n        EditorSceneManager.MarkAllScenesDirty();\n    }\n\n    public static Mesh CombineMeshRender(string prefixName, GameObject rootObj, List&lt;GameObject> input)\n    {\n        var matrix = rootObj.transform.worldToLocalMatrix;\n\n        CombineInstance[] combine = new CombineInstance[input.Count];\n        for(int i=0; i&lt;input.Count; ++i)\n        {\n            var mf = input[i].GetComponent&lt;MeshFilter>();\n            combine[i].mesh = mf.sharedMesh;\n            combine[i].transform = matrix * mf.transform.localToWorldMatrix;\n        }\n        \n        Mesh mesh = new Mesh();\n        mesh.CombineMeshes(combine, true);\n\n        var number = string.Empty;\n        string assetPath = string.Empty;\n        for(int i=0; i&lt;100; ++i)\n        {\n            number = Random.Range(100000, 900000).ToString();\n            assetPath = \"Assets\/Arts\/CombineMesh\/\" + prefixName + \"_\"+  number + \".asset\";\n            if (!System.IO.File.Exists(assetPath))\n            {\n                break;\n            }\n        }\n\n        AssetDatabase.CreateAsset(mesh , assetPath);\n        AssetDatabase.SaveAssets();\n\n        var meshRet = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Mesh)) as Mesh;\n        return meshRet;\n    }\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/864"}],"collection":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=864"}],"version-history":[{"count":3,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/864\/revisions"}],"predecessor-version":[{"id":947,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/864\/revisions\/947"}],"wp:attachment":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=864"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=864"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=864"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}