unity换装系统+网格合并

这里的做法是模型把所有衣服全部穿上作为一个资源

然后还有一个只有骨骼信息的骨架资源

将这2个制作好了Prefab

模型部件数据

资源数据

 

 

【代码】

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AvatarSystem : MonoBehaviour {

    //模型全文件
    GameObject modelObject;
    Transform modelSource;
    //骨骼文件
    GameObject targetSource;
    Transform targetTrans;
    //Data字典 存储source的各种信息;
    private Dictionary<string, Dictionary<string, Transform>> data = new Dictionary<string, Dictionary<string, Transform>>();
    //targetSmr字典 存储目标的骨骼信息
    private Dictionary<string, SkinnedMeshRenderer> targetSmr = new Dictionary<string, SkinnedMeshRenderer>();
    //骨骼数组
    private Transform[] hips;
    //套装数据
    string[,] avatarStr = new string[,] { { "Glove", "suit01" }, { "Head", "suit01" }, { "Hair", "suit01" }, { "Body", "suit02" }, { "Leg", "suit03" }, { "Shoe", "suit03" } };

    // Use this for initialization
    void Start () {
        InstantiateAvatar("Prefab/Model_girl");//读取模型文件
        InstantiateSkeleton("Prefab/Target_girl");//读取骨架文件
        LoadAvatarData(modelSource);//读取模型所有衣服数据,并且存储
        hips = targetTrans.GetComponentsInChildren<Transform>();//拿取人物骨骼信息
        Inivatar(avatarStr);//换上套装
        //targetSource.AddComponent<Animator>();
    }
    
    // Update is called once per frame
    void Update () {
        
    }


    //实例化来源
    void InstantiateAvatar(string modelName)
    {
        //必需得实例化出来,不然无法获得数据
        modelObject = (Instantiate(Resources.Load<GameObject>(modelName)));
        modelSource = modelObject.transform;
        modelSource.gameObject.SetActive(false);//隐藏
        //Destroy(modelObject);//销毁
    }
    //实例化骨架(换装就是在骨架上加衣服)
    void InstantiateSkeleton(string targetName)
    {
        targetSource = Instantiate(Resources.Load<GameObject>(targetName));
        targetTrans = targetSource.transform;
    }
    //读取来源的各种信息(source模型源文件)
    void LoadAvatarData(Transform source)
    {
        if (source == null)
        {
            return;
        }
        SkinnedMeshRenderer[] parts = source.GetComponentsInChildren<SkinnedMeshRenderer>(true);
        foreach (SkinnedMeshRenderer part in parts)
        {
            string[] partName = part.name.Split('_');
            if (!data.ContainsKey(partName[0]))
            {
                data.Add(partName[0], new Dictionary<string, Transform>());
                GameObject partObj = new GameObject();
                partObj.name = partName[0];
                partObj.transform.parent = targetTrans;
                targetSmr.Add(partName[0], partObj.AddComponent<SkinnedMeshRenderer>());
            }
            data[partName[0]].Add(partName[1], part.transform);
        }
    }
    //更改Mesh
    public void ChangeMesh(string part, string item)
    {
        SkinnedMeshRenderer smr = data[part][item].GetComponent<SkinnedMeshRenderer>();
        //网格合并
        List<CombineInstance> combineInstances = new List<CombineInstance>();
        for (int i = 0; i < smr.sharedMesh.subMeshCount; i++)
        {
            CombineInstance ci = new CombineInstance();
            ci.mesh = smr.sharedMesh;
            ci.subMeshIndex = i;
            combineInstances.Add(ci);
        }
        List<Transform> bones = new List<Transform>();
        foreach (Transform bone in smr.bones)
        {
            foreach (Transform hip in hips)
            {
                if (hip.name != bone.name)
                {
                    continue;
                }
                bones.Add(hip);
                break;
            }
        }

        //网格合并方式
        targetSmr[part].sharedMesh = new Mesh();
        targetSmr[part].sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false);
        //非网格合并方式
        //targetSmr[part].sharedMesh = smr.sharedMesh;
        targetSmr[part].bones = bones.ToArray();
        targetSmr[part].materials = smr.materials;


    }

    /// <summary>
    /// 换装(换1件到多件)
    /// </summary>
    /// <param name="avatarStr"></param>
    public void Inivatar(string[,] avatarStr)
    {
        int nLength = avatarStr.GetLength(0);
        for (int i = 0; i < nLength; i++)
        {
            ChangeMesh(avatarStr[i, 0], avatarStr[i, 1]);
        }
    }
}

 

posted @ 2018-05-30 14:52  三页菌  阅读(493)  评论(0编辑  收藏  举报