public class MeshRendererUtility
{
public static void Merge(Transform transform)
{
var skins = transform.GetComponentsInChildren<SkinnedMeshRenderer>().Where(x=>x.sharedMesh!=null).ToArray();
List<Material> materials = new List<Material>();
List<Mesh> meshes = new List<Mesh>();
List<Texture2D> textures = new List<Texture2D>();
foreach (var skin in skins)
{
meshes.Add(skin.sharedMesh);
foreach (var mat in skin.sharedMaterials)
{
materials.Add(mat);
var texture = mat.GetTexture("_MainTex") as Texture2D;
if (texture != null)
{
textures.Add(texture);
}
}
}
var rects = MergeTexture(textures.ToArray(), out Texture2D result);
var material = MergeMaterial(materials.ToArray(), result);
var mesh = MergeMesh(meshes.ToArray(), rects);
mesh.bindposes = GetMeshBindPoses(skins[0].bones, transform);
var skinned = transform.gameObject.AddComponent<SkinnedMeshRenderer>();
skinned.rootBone = skins[0].rootBone;
skinned.bones = skins[0].bones;
skinned.sharedMesh = mesh;
skinned.material = material;
}
public static Mesh MergeMesh(Mesh[]meshes,Rect[] rects)
{
CombineInstance[] combineInstances = new CombineInstance[meshes.Length];
List<BoneWeight> boneWeights = new List<BoneWeight>();
for (int i=0;i<meshes.Length;i++)
{
var rect = rects[i];
Mesh mesh = new Mesh();
mesh.vertices = meshes[i].vertices;
mesh.triangles = meshes[i].triangles;
mesh.normals = meshes[i].normals;
boneWeights.AddRange(meshes[i].boneWeights);
Vector2 []uvs = new Vector2[meshes[i].uv.Length];
for (int j = 0; j < uvs.Length; j++)
{
uvs[j].x = rect.x + meshes[i].uv[j].x * rect.width;
uvs[j].y = rect.y + meshes[i].uv[j].y * rect.height;
}
mesh.uv = uvs;
combineInstances[i] = new CombineInstance {
mesh=mesh };
}
Mesh result = new Mesh();
result.CombineMeshes(combineInstances, true, false);
result.boneWeights = boneWeights.ToArray();
return result;
}
public static Rect[] MergeTexture(Texture2D [] textures,out Texture2D result)
{
result = new Texture2D(1024, 1024);
string[] assetPaths = new string[textures.Length];
for (int i=0;i<textures.Length;i++)
{
assetPaths[i] = AssetDatabase.GetAssetPath(textures[i]);
}
Texture2D[] newTextures = new Texture2D[textures.Length];
for(int i=0;i<textures.Length;i++)
{
var texture = textures[i];
newTextures[i] = GetTexture(texture);
}
for (int i = 0; i < assetPaths.Length; i++)
{
AssetDatabase.DeleteAsset(assetPaths[i]);
}
var rects = result.PackTextures(newTextures, 0, 1024);
for (int i=0;i< newTextures.Length;i++)
{
UnityEngine.Object.DestroyImmediate(newTextures[i]);
}
return rects;
}
static Texture2D GetTexture(Texture2D texture)
{
RenderTexture renderTexture = new RenderTexture(texture.width, texture.height, 0);
Graphics.Blit(texture, renderTexture);
Texture2D texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
var rt = RenderTexture.active;
RenderTexture.active = renderTexture;
texture2D.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
texture2D.Apply();
RenderTexture.active = rt;
UnityEngine.Object.DestroyImmediate(renderTexture);
return texture2D;
}
static Material MergeMaterial(Material[] materials,Texture2D texture)
{
Material material = new Material(materials[0].shader);
material.CopyPropertiesFromMaterial(materials[0]);
material.SetTexture("_MainTex", texture);
return material;
}
static Matrix4x4[] GetMeshBindPoses(Transform[] transforms, Transform transform)
{
Matrix4x4[] bindPoses = new Matrix4x4[transforms.Length];
for (int i = 0; i < transforms.Length; i++)
{
bindPoses[i] = transforms[i].worldToLocalMatrix * transform.localToWorldMatrix;
}
return bindPoses;
}
}
Merge multiple SkinnedMeshRenderers on the same bone
Guess you like
Origin blog.csdn.net/qq_17813937/article/details/130150657
Recommended
Ranking