1 Star 0 Fork 14

Taopper/UnityFun

forked from 陈勇星/UnityFun 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
CombineMesh.cs 12.80 KB
一键复制 编辑 原始数据 按行查看 历史
using UnityEngine;
using System.Collections.Generic;
public class CombineMesh : MonoBehaviour
{
public GameObject skeleton;
public GameObject face;
public GameObject hands;
public GameObject lower;
public GameObject upper;
public GameObject weapon;
void EquipWeapon(int hand, GameObject avatar, GameObject weapon)
{
Transform handTransform = null;
if (hand == 1)
{
handTransform = avatar.transform.FindChild("Bip01/dummy_right_weapon_at");
}
else
{
handTransform = avatar.transform.FindChild("Bip01/dummy_left_weapon_at");
}
var weaponTransform = weapon.transform;
weaponTransform.SetParent(handTransform);
weaponTransform.localPosition = Vector3.zero;
weaponTransform.localRotation = Quaternion.identity;
weaponTransform.localScale = Vector3.one;
}
void ReplaceElement(int elementType, GameObject avatar, GameObject dummy)
{
if (elementType == 1) //头
{
var dummyElement = dummy.transform.FindChild("face").gameObject;
var avatarElement = avatar.transform.FindChild("face").gameObject;
dummyElement.transform.SetParent(avatar.transform);
GameObject.Destroy(dummy);
GameObject.Destroy(avatarElement);
var skinnedMeshRenderer = dummyElement.GetComponent<SkinnedMeshRenderer>();
var avatarBones = avatar.GetComponentsInChildren<Transform>();
List<Transform> newBones = new List<Transform>();
foreach (Transform bone in skinnedMeshRenderer.bones)
{
foreach (Transform avatarBone in avatarBones)
{
//找对应骨骼进行替换
if (avatarBone.name.Equals(bone.name))
{
newBones.Add(avatarBone);
break;
}
}
}
skinnedMeshRenderer.bones = newBones.ToArray();
}
}
void OnGUI()
{
if (GUI.Button(new Rect(50, 400, 100, 50), "替换骨骼"))
{
ReplaceElement(1, skeleton, face);
EquipWeapon(2, skeleton, weapon);
return;
var faceSMR = face.GetComponentInChildren<SkinnedMeshRenderer>();
faceSMR.transform.SetParent(skeleton.transform);
GameObject.DestroyImmediate(skeleton.transform.FindChild("face").gameObject);
var avatarBones = gameObject.GetComponentsInChildren<Transform>();
List<Transform> newBones = new List<Transform>();
foreach (Transform bone in faceSMR.bones)
{
foreach (Transform avatarBone in avatarBones)
{
if (avatarBone.name.Equals(bone.name))
{
avatarBone.localPosition = bone.localPosition;
avatarBone.localScale = bone.localScale;
avatarBone.localRotation = bone.localRotation;
newBones.Add(avatarBone);
break;
}
}
}
faceSMR.bones = newBones.ToArray();
}
if (GUI.Button(new Rect(50, 300, 100, 50), "换头2"))
{
SkinnedMeshRenderer[] meshes = new SkinnedMeshRenderer[4];
GameObject[] objects = new GameObject[4];
meshes[0] = face.GetComponentInChildren<SkinnedMeshRenderer>();
meshes[1] = hands.GetComponentInChildren<SkinnedMeshRenderer>();
meshes[2] = lower.GetComponentInChildren<SkinnedMeshRenderer>();
meshes[3] = upper.GetComponentInChildren<SkinnedMeshRenderer>();
CombineObject(skeleton, meshes, false);
}
if (GUI.Button(new Rect(50, 100, 100, 50), "换头1"))
{
MergeChild(skeleton);
return;
//目标部件
//var targetSMRs = face.GetComponentsInChildren<SkinnedMeshRenderer>();
//SkinnedMeshRenderer targetSMR = null;
//for (int i = 0; i < targetSMRs.Length; i++)
//{
// if (targetSMRs[i].gameObject.name.Equals("face"))
// {
// targetSMR = targetSMRs[i];
// break;
// }
//}
//裸体原型
List<Material> materials = new List<Material>();
List<CombineInstance> combineInstances = new List<CombineInstance>();
List<Transform> bones = new List<Transform>();
//bones.AddRange(skeleton.transform.FindChild("Bip01").GetComponentsInChildren<Transform>(true));
Matrix4x4 myTransform = skeleton.transform.worldToLocalMatrix;
var nudeSMRs = skeleton.GetComponentsInChildren<SkinnedMeshRenderer>();
for (int i = 0; i < nudeSMRs.Length; i++)
{
SkinnedMeshRenderer skinnedMeshRenderer = nudeSMRs[i];
foreach (Transform bone in skinnedMeshRenderer.bones)
{
bones.Add(bone);
}
//材质
materials.AddRange(skinnedMeshRenderer.materials);
//网格
CombineInstance combine = new CombineInstance();
combine.mesh = skinnedMeshRenderer.sharedMesh;
combine.transform = myTransform * skinnedMeshRenderer.transform.localToWorldMatrix;
combineInstances.Add(combine);
for (int sub = 0; sub < skinnedMeshRenderer.sharedMesh.subMeshCount; sub++)
{
combine.subMeshIndex = sub;
//combineInstances.Add(combine);
}
skinnedMeshRenderer.gameObject.SetActive(false);
//if (nudeSMRs[i].gameObject.name.Equals("face"))
//{
// nudeSMRs[i].gameObject.SetActive(false);
//}
}
List<Matrix4x4> bindposes = new List<Matrix4x4>();
for (int i = 0; i < bones.Count; i++)
{
bindposes.Add(bones[i].worldToLocalMatrix * skeleton.transform.worldToLocalMatrix);
}
//合并
SkinnedMeshRenderer smr = skeleton.AddComponent<SkinnedMeshRenderer>();
smr.materials = materials.ToArray();
smr.sharedMesh = new Mesh();
smr.sharedMesh.name = skeleton.name;
smr.sharedMesh.CombineMeshes(combineInstances.ToArray(), false);
//smr.sharedMesh.bindposes = bindposes.ToArray();
smr.sharedMesh.RecalculateBounds();
smr.bones = bones.ToArray();
}
}
public static void MergeChild(GameObject gameObject)
{
if (gameObject.GetComponent<SkinnedMeshRenderer>() != null)
{
//LogTool.Error("合并结果对象不能有SkinnedMeshRenderer");
return;
}
var meshRenderers = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
List<BoneWeight> boneWeights = new List<BoneWeight>();
List<Transform> bones = new List<Transform>();
List<CombineInstance> combines = new List<CombineInstance>();
List<Material> materials = new List<Material>();
int boneOffset = 0;
for (int i = 0; i < meshRenderers.Length; i++)
{
SkinnedMeshRenderer skinnedMeshRenderer = meshRenderers[i];
if (skinnedMeshRenderer.sharedMesh.triangles.Length == 0)
{
Debug.LogError(skinnedMeshRenderer.gameObject.name + "模型网格顶点数据为空!检查导入模型Read/Write Enabled");
return;
}
BoneWeight[] meshBoneweight = skinnedMeshRenderer.sharedMesh.boneWeights;
foreach (BoneWeight bw in meshBoneweight)
{
BoneWeight bWeight = bw;
bWeight.boneIndex0 += boneOffset;
bWeight.boneIndex1 += boneOffset;
bWeight.boneIndex2 += boneOffset;
bWeight.boneIndex3 += boneOffset;
boneWeights.Add(bWeight);
}
boneOffset += skinnedMeshRenderer.bones.Length;
foreach (Transform bone in skinnedMeshRenderer.bones)
{
bool contain = false;
foreach (Transform bone2 in bones)
{
if (bone2.name.Equals(bone.name))
{
contain = true;
}
}
if (!contain)
{
bones.Add(bone);
}
}
//combines[i].mesh = skinnedMeshRenderer.sharedMesh;
//combines[i].transform = skinnedMeshRenderer.transform.localToWorldMatrix;
//materials[i] = skinnedMeshRenderer.sharedMaterial;
//材质
materials.AddRange(skinnedMeshRenderer.materials);
//网格
CombineInstance combine = new CombineInstance();
combine.mesh = skinnedMeshRenderer.sharedMesh;
combine.transform = skinnedMeshRenderer.transform.localToWorldMatrix;
for (int sub = 0; sub < skinnedMeshRenderer.sharedMesh.subMeshCount; sub++)
{
combine.subMeshIndex = sub;
combines.Add(combine);
}
GameObject.Destroy(skinnedMeshRenderer.gameObject);
}
List<Matrix4x4> bindposes = new List<Matrix4x4>();
for (int i = 0; i < bones.Count; i++)
{
bindposes.Add(bones[i].worldToLocalMatrix * gameObject.transform.worldToLocalMatrix);
}
SkinnedMeshRenderer meshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = gameObject.AddComponent<SkinnedMeshRenderer>();
}
meshRenderer.sharedMesh = new Mesh();
meshRenderer.sharedMesh.name = gameObject.name;
meshRenderer.sharedMesh.CombineMeshes(combines.ToArray(), false);
meshRenderer.bones = bones.ToArray();
//meshRenderer.sharedMesh.boneWeights = boneWeights.ToArray();
meshRenderer.sharedMesh.bindposes = bindposes.ToArray();
meshRenderer.sharedMesh.RecalculateBounds();
meshRenderer.sharedMaterials = materials.ToArray();
}
/// <summary>
/// Combine SkinnedMeshRenderers together and share one skeleton.
/// Merge materials will reduce the drawcalls, but it will increase the size of memory.
/// </summary>
/// <param name="skeleton">combine meshes to this skeleton(a gameobject)</param>
/// <param name="meshes">meshes need to be merged</param>
/// <param name="combine">merge materials or not</param>
public void CombineObject(GameObject skeleton, SkinnedMeshRenderer[] meshes, bool combine = false)
{
// Fetch all bones of the skeleton
List<Transform> transforms = new List<Transform>();
transforms.AddRange(skeleton.GetComponentsInChildren<Transform>(true));
List<Material> materials = new List<Material>();//the list of materials
List<CombineInstance> combineInstances = new List<CombineInstance>();//the list of meshes
List<Transform> bones = new List<Transform>();//the list of bones
// Collect information from meshes
for (int i = 0; i < meshes.Length; i++)
{
SkinnedMeshRenderer smr = meshes[i];
materials.AddRange(smr.materials); // Collect materials
// Collect meshes
for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
{
CombineInstance ci = new CombineInstance();
ci.mesh = smr.sharedMesh;
ci.subMeshIndex = sub;
combineInstances.Add(ci);
}
// Collect bones
for (int j = 0; j < smr.bones.Length; j++)
{
int tBase = 0;
for (tBase = 0; tBase < transforms.Count; tBase++)
{
if (smr.bones[j].name.Equals(transforms[tBase].name))
{
bones.Add(transforms[tBase]);
break;
}
}
}
}
// Create a new SkinnedMeshRenderer
SkinnedMeshRenderer oldSKinned = skeleton.GetComponent<SkinnedMeshRenderer>();
if (oldSKinned != null)
{
GameObject.DestroyImmediate(oldSKinned);
}
SkinnedMeshRenderer r = skeleton.AddComponent<SkinnedMeshRenderer>();
r.sharedMesh = new Mesh();
r.sharedMesh.CombineMeshes(combineInstances.ToArray(), combine, false);// Combine meshes
r.bones = bones.ToArray();// Use new bones
r.materials = materials.ToArray();
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/Taopper/UnityFun.git
git@gitee.com:Taopper/UnityFun.git
Taopper
UnityFun
UnityFun
master

搜索帮助