Unity人物换装 合并网格材质骨骼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
struct meshT
{
public Mesh _mesh;
public Transform[] _transform;
public Material _material;
///换装并合并网格
/// </summary>
public class MeshMergeDome2 : MonoBehaviour
{
public static MeshMergeDome2 _intance;
private void Awake()
{
_intance = this;
}
public string loadName;
//生成人物得位置
private Transform StartPos;
private GameObject gamePlayerObj;
Dictionary<string, meshT> meshDic = new Dictionary<string, meshT>();
Dictionary<string, meshT> meshTs = new Dictionary<string, meshT>();
private string rootNamne;
Material[] material;
Transform[] _transform;
/// <summary>
/// 初始化
/// </summary>
private void Start()
{
//寻找生成位置
StartPos = GameObject.FindGameObjectWithTag("StartPos").transform;
//加载人物
gamePlayerObj = Instantiate(Resources.Load<GameObject>(loadName), StartPos.position, Quaternion.identity);
SkinnedMeshRenderer[] skinnedMeshRenderers = gamePlayerObj.GetComponentsInChildren<SkinnedMeshRenderer>();
for (int i = 0; i < skinnedMeshRenderers.Length; i++)
{
meshDic.Add(skinnedMeshRenderers[i].name, new meshT() { _mesh = skinnedMeshRenderers[i].sharedMesh, _transform = skinnedMeshRenderers[i].bones, _material = skinnedMeshRenderers[i].sharedMaterial,/*_transform1 = gamePlayerObj.transform.worldToLocalMatrix * skinnedMeshRenderers[i].transform.localToWorldMatrix*/ });
Destroy(skinnedMeshRenderers[i].gameObject);
}
List<Transform> boneList = new List<Transform>();
Transform[] transforms = gamePlayerObj.transform.Find("Female_Hips").GetComponentsInChildren<Transform>();
foreach (KeyValuePair<string, meshT> item in meshDic)
{
string name = item.Key.Split('-')[0];
if (name != rootNamne)
{
meshTs.Add(name, item.Value);
for (int i = 0; i < item.Value._transform.Length; i++)
{
boneList.Add(item.Value._transform[i]);
}
rootNamne = name;
}
}
CombineInstance[] combineInstances = new CombineInstance[meshTs.Count];
List<meshT> mesh = new List<meshT>();
foreach (var item in meshTs)
{
mesh.Add(item.Value);
}
material = new Material[mesh.Count];
_transform = new Transform[mesh.Count];
List<Vector2[]> uvList = new List<Vector2[]>();//uv坐标
int uvCount = 0;
for (int i = 0; i < mesh.Count; i++)
{
uvList.Add(mesh[i]._mesh.uv);//存储uv坐标
uvCount += mesh[i]._mesh.uv.Length;
material[i] = mesh[i]._material;
combineInstances[i].mesh = mesh[i]._mesh;
}
List<Texture2D> textures = new List<Texture2D>();
int width = 0;
int height = 0;
//存储图片信息
foreach (Material item in material)
{
if (item.mainTexture != null)
{
textures.Add(item.mainTexture as Texture2D);
width += item.mainTexture.width;
height += item.mainTexture.height;
}
}
SkinnedMeshRenderer skinned = gamePlayerObj.AddComponent<SkinnedMeshRenderer>();
// 设置贴图和UV
skinned.sharedMesh = new Mesh();
skinned.sharedMesh.CombineMeshes(combineInstances, true, false); //不在意的矩阵的变换
skinned.bones = boneList.ToArray();
skinned.material = material[0];
//创建一个空的图片
Texture2D skinnedMeshAtlas = new Texture2D(get2Pow(width), get2Pow(height));
Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
Vector2[] atlasUVs = new Vector2[uvCount];
// 因为将贴图都整合到了一张图片上,所以需要重新计算UV
int j = 0;
for (int i = 0; i < uvList.Count; i++)
{
foreach (Vector2 uv in uvList[i])
{
atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
j++;
}
}
skinned.material.mainTexture = skinnedMeshAtlas;
skinned.sharedMesh.uv = atlasUVs;
//MergeMesh(skinned, combineInstances, boneList);
}
/// <summary>
/// 合并网格、材质、骨骼
/// </summary>
/// <param name="skinned"></param>
/// <param name="combineInstances"></param>
/// <param name="boneList"></param>
void MergeMesh(SkinnedMeshRenderer skinned, CombineInstance[] combineInstances, List<Transform> boneList)
{
skinned.sharedMesh = new Mesh();
skinned.sharedMesh.CombineMeshes(combineInstances, false, false); //不在意的矩阵的变换
skinned.materials = material;
skinned.bones = boneList.ToArray();
}
public void UpdateMesh(string meshName)
{
string UpdateName = "";
/// <summary>
/// 当前的人物换装信息
/// </summary>
Dictionary<string, meshT> currmesh = meshTs;
foreach (KeyValuePair<string, meshT> item in currmesh)
{
string name = item.Key.Split('-')[0];
if (name == meshName.Split('-')[0])
{
UpdateName = item.Key;
}
}
currmesh[UpdateName] = meshDic[meshName];
List<Transform> boneList = new List<Transform>();
foreach (KeyValuePair<string, meshT> item in currmesh)
{
for (int i = 0; i < item.Value._transform.Length; i++)
{
boneList.Add(item.Value._transform[i]);
}
}
CombineInstance[] combineInstances = new CombineInstance[meshTs.Count];
List<meshT> mesh = new List<meshT>();
foreach (var item in currmesh)
{
mesh.Add(item.Value);
}
List<Vector2[]> uvList = new List<Vector2[]>();//uv坐标
int uvCount = 0;
for (int i = 0; i < mesh.Count; i++)
{
uvList.Add(mesh[i]._mesh.uv);//存储uv坐标
uvCount += mesh[i]._mesh.uv.Length;
material[i] = mesh[i]._material;
combineInstances[i].mesh = mesh[i]._mesh;
}
material = new Material[mesh.Count];
_transform = new Transform[mesh.Count];
for (int i = 0; i < mesh.Count; i++)
{
material[i] = mesh[i]._material;
combineInstances[i].mesh = mesh[i]._mesh;
}
List<Texture2D> textures = new List<Texture2D>();
int width = 0;
int height = 0;
//存储图片信息
foreach (Material item in material)
{
if (item.mainTexture != null)
{
textures.Add(item.mainTexture as Texture2D);
width += item.mainTexture.width;
height += item.mainTexture.height;
}
}
SkinnedMeshRenderer skinned = gamePlayerObj.GetComponent<SkinnedMeshRenderer>();
skinned.sharedMesh = new Mesh();
skinned.sharedMesh.CombineMeshes(combineInstances, true, false); //不在意的矩阵的变换
skinned.bones = boneList.ToArray();
skinned.material = material[0];
//创建一个空的图片
Texture2D skinnedMeshAtlas = new Texture2D(get2Pow(width), get2Pow(height));
Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
Vector2[] atlasUVs = new Vector2[uvCount];
// 因为将贴图都整合到了一张图片上,所以需要重新计算UV
int j = 0;
for (int i = 0; i < uvList.Count; i++)
{
foreach (Vector2 uv in uvList[i])
{
atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
j++;
}
}
skinned.material.mainTexture = skinnedMeshAtlas;
skinned.sharedMesh.uv = atlasUVs;
//MergeMesh(skinned, combineInstances, boneList);
}
/// <summary>
/// 获取最接近输入值的2的N次方的数,最大不会超过1024,例如输入320会得到512
/// </summary>
public int get2Pow(int into)
{
int outo = 1;
for (int i = 0; i < 10; i++)
{
outo *= 2;
if (outo > into)
{
break;
}
}
return outo;
}
using System.Collections.Generic;
using UnityEngine;
struct meshT
{
public Mesh _mesh;
public Transform[] _transform;
public Material _material;
}
///换装并合并网格
/// </summary>
public class MeshMergeDome2 : MonoBehaviour
{
public static MeshMergeDome2 _intance;
private void Awake()
{
_intance = this;
}
public string loadName;
//生成人物得位置
private Transform StartPos;
private GameObject gamePlayerObj;
Dictionary<string, meshT> meshDic = new Dictionary<string, meshT>();
Dictionary<string, meshT> meshTs = new Dictionary<string, meshT>();
private string rootNamne;
Material[] material;
Transform[] _transform;
/// <summary>
/// 初始化
/// </summary>
private void Start()
{
//寻找生成位置
StartPos = GameObject.FindGameObjectWithTag("StartPos").transform;
//加载人物
gamePlayerObj = Instantiate(Resources.Load<GameObject>(loadName), StartPos.position, Quaternion.identity);
SkinnedMeshRenderer[] skinnedMeshRenderers = gamePlayerObj.GetComponentsInChildren<SkinnedMeshRenderer>();
for (int i = 0; i < skinnedMeshRenderers.Length; i++)
{
meshDic.Add(skinnedMeshRenderers[i].name, new meshT() { _mesh = skinnedMeshRenderers[i].sharedMesh, _transform = skinnedMeshRenderers[i].bones, _material = skinnedMeshRenderers[i].sharedMaterial,/*_transform1 = gamePlayerObj.transform.worldToLocalMatrix * skinnedMeshRenderers[i].transform.localToWorldMatrix*/ });
Destroy(skinnedMeshRenderers[i].gameObject);
}
List<Transform> boneList = new List<Transform>();
Transform[] transforms = gamePlayerObj.transform.Find("Female_Hips").GetComponentsInChildren<Transform>();
foreach (KeyValuePair<string, meshT> item in meshDic)
{
string name = item.Key.Split('-')[0];
if (name != rootNamne)
{
meshTs.Add(name, item.Value);
for (int i = 0; i < item.Value._transform.Length; i++)
{
boneList.Add(item.Value._transform[i]);
}
rootNamne = name;
}
}
CombineInstance[] combineInstances = new CombineInstance[meshTs.Count];
List<meshT> mesh = new List<meshT>();
foreach (var item in meshTs)
{
mesh.Add(item.Value);
}
material = new Material[mesh.Count];
_transform = new Transform[mesh.Count];
List<Vector2[]> uvList = new List<Vector2[]>();//uv坐标
int uvCount = 0;
for (int i = 0; i < mesh.Count; i++)
{
uvList.Add(mesh[i]._mesh.uv);//存储uv坐标
uvCount += mesh[i]._mesh.uv.Length;
material[i] = mesh[i]._material;
combineInstances[i].mesh = mesh[i]._mesh;
}
List<Texture2D> textures = new List<Texture2D>();
int width = 0;
int height = 0;
//存储图片信息
foreach (Material item in material)
{
if (item.mainTexture != null)
{
textures.Add(item.mainTexture as Texture2D);
width += item.mainTexture.width;
height += item.mainTexture.height;
}
}
SkinnedMeshRenderer skinned = gamePlayerObj.AddComponent<SkinnedMeshRenderer>();
// 设置贴图和UV
skinned.sharedMesh = new Mesh();
skinned.sharedMesh.CombineMeshes(combineInstances, true, false); //不在意的矩阵的变换
skinned.bones = boneList.ToArray();
skinned.material = material[0];
//创建一个空的图片
Texture2D skinnedMeshAtlas = new Texture2D(get2Pow(width), get2Pow(height));
Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
Vector2[] atlasUVs = new Vector2[uvCount];
// 因为将贴图都整合到了一张图片上,所以需要重新计算UV
int j = 0;
for (int i = 0; i < uvList.Count; i++)
{
foreach (Vector2 uv in uvList[i])
{
atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
j++;
}
}
skinned.material.mainTexture = skinnedMeshAtlas;
skinned.sharedMesh.uv = atlasUVs;
//MergeMesh(skinned, combineInstances, boneList);
}
/// <summary>
/// 合并网格、材质、骨骼
/// </summary>
/// <param name="skinned"></param>
/// <param name="combineInstances"></param>
/// <param name="boneList"></param>
void MergeMesh(SkinnedMeshRenderer skinned, CombineInstance[] combineInstances, List<Transform> boneList)
{
skinned.sharedMesh = new Mesh();
skinned.sharedMesh.CombineMeshes(combineInstances, false, false); //不在意的矩阵的变换
skinned.materials = material;
skinned.bones = boneList.ToArray();
}
public void UpdateMesh(string meshName)
{
string UpdateName = "";
/// <summary>
/// 当前的人物换装信息
/// </summary>
Dictionary<string, meshT> currmesh = meshTs;
foreach (KeyValuePair<string, meshT> item in currmesh)
{
string name = item.Key.Split('-')[0];
if (name == meshName.Split('-')[0])
{
UpdateName = item.Key;
}
}
currmesh[UpdateName] = meshDic[meshName];
List<Transform> boneList = new List<Transform>();
foreach (KeyValuePair<string, meshT> item in currmesh)
{
for (int i = 0; i < item.Value._transform.Length; i++)
{
boneList.Add(item.Value._transform[i]);
}
}
CombineInstance[] combineInstances = new CombineInstance[meshTs.Count];
List<meshT> mesh = new List<meshT>();
foreach (var item in currmesh)
{
mesh.Add(item.Value);
}
List<Vector2[]> uvList = new List<Vector2[]>();//uv坐标
int uvCount = 0;
for (int i = 0; i < mesh.Count; i++)
{
uvList.Add(mesh[i]._mesh.uv);//存储uv坐标
uvCount += mesh[i]._mesh.uv.Length;
material[i] = mesh[i]._material;
combineInstances[i].mesh = mesh[i]._mesh;
}
material = new Material[mesh.Count];
_transform = new Transform[mesh.Count];
for (int i = 0; i < mesh.Count; i++)
{
material[i] = mesh[i]._material;
combineInstances[i].mesh = mesh[i]._mesh;
}
List<Texture2D> textures = new List<Texture2D>();
int width = 0;
int height = 0;
//存储图片信息
foreach (Material item in material)
{
if (item.mainTexture != null)
{
textures.Add(item.mainTexture as Texture2D);
width += item.mainTexture.width;
height += item.mainTexture.height;
}
}
SkinnedMeshRenderer skinned = gamePlayerObj.GetComponent<SkinnedMeshRenderer>();
skinned.sharedMesh = new Mesh();
skinned.sharedMesh.CombineMeshes(combineInstances, true, false); //不在意的矩阵的变换
skinned.bones = boneList.ToArray();
skinned.material = material[0];
//创建一个空的图片
Texture2D skinnedMeshAtlas = new Texture2D(get2Pow(width), get2Pow(height));
Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
Vector2[] atlasUVs = new Vector2[uvCount];
// 因为将贴图都整合到了一张图片上,所以需要重新计算UV
int j = 0;
for (int i = 0; i < uvList.Count; i++)
{
foreach (Vector2 uv in uvList[i])
{
atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
j++;
}
}
skinned.material.mainTexture = skinnedMeshAtlas;
skinned.sharedMesh.uv = atlasUVs;
//MergeMesh(skinned, combineInstances, boneList);
}
/// <summary>
/// 获取最接近输入值的2的N次方的数,最大不会超过1024,例如输入320会得到512
/// </summary>
public int get2Pow(int into)
{
int outo = 1;
for (int i = 0; i < 10; i++)
{
outo *= 2;
if (outo > into)
{
break;
}
}
return outo;
}
}
效果: