代码拉取完成,页面将自动刷新
同步操作将从 陈勇星/UnityFun 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
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();
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。