uinty SkinnedMeshRenderer 实现换装系统 (更换模型节点)


 

人物基本模型,在group2下包含基本节点

装备模型 ,在group2下包含所需装备
基本换装思路就是:根据所需装备将 将装备模型 group2下的SkinnedMeshRenderer复制到人物模型中

    //获取主人物模型
    void InstantiateSkeleton()
    {
        targetobj = Instantiate(Resources.Load("Play")) as GameObject;
        target = targetobj.transform;
    }

    //获取装备模型
    void InstantiateAvatar()
    {
        sourceobj = Instantiate(Resources.Load("Zhuangbei")) as GameObject;
        source = sourceobj.transform;
        sourceobj.SetActive(false);
    }

找到装备模型中的包含的SkinnedMeshRenderer保存下来,并在人物模型中生成对应节点

    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 = target.Find("group2");

                targetSmr.Add(partName[0], partObj.AddComponent<SkinnedMeshRenderer>());
            }
             data[partName[0]].Add(partName[1], part.transform);
        }
    }
根据选择的装备 将对应的 SkinnedMeshRenderer复制到人物模型中 对应节点
    void ChangePart(string part, string item)
    {
        //从资料中取得各部位指定编号的 SkinnedMeshRenderer
        SkinnedMeshRenderer smr = data[part][item].GetComponent<SkinnedMeshRenderer>();

        //取得相对应名称的骨架物件来建立新的骨架列表
        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;
            }
        }
        // 更新指定部位 GameObject 的 SkinnedMeshRenderer 内容
        targetSmr[part].sharedMesh = smr.sharedMesh;
        targetSmr[part].bones = bones.ToArray();
        targetSmr[part].materials = smr.materials;
        //一般到上面就可以了,但我那模型不知道是不是我改节点弄坏了,
        foreach (Transform hip in hips)
        {
            if (hip.name != smr.rootBone.name) continue;
            targetSmr[part].rootBone = hip;
            break;
        }
    }
具体代码:
using UnityEngine;
using System.Collections.Generic;

public class Dressing : MonoBehaviour
{
    private Transform source;
    private Transform target;

    private GameObject sourceobj;
    private GameObject targetobj;

    private Dictionary<string, Dictionary<string, Transform>> data = new Dictionary<string, Dictionary<string, Transform>>();
    private Transform[] hips;
    private Dictionary<string, SkinnedMeshRenderer> targetSmr = new Dictionary<string, SkinnedMeshRenderer>();

    public static Dressing instance;

    // Use this for initialization  
    void Start()
    {
        instance = this;

        InstantiateSkeleton();
        InstantiateAvatar();
        LoadAvatarData(source);
        hips = target.GetComponentsInChildren<Transform>();
    }

    // Update is called once per frame  
    void Update()
    {

    }

    //获取主人物模型
    void InstantiateSkeleton()
    {
        targetobj = Instantiate(Resources.Load("Play")) as GameObject;
        target = targetobj.transform;
    }

    //获取装备模型
    void InstantiateAvatar()
    {
        sourceobj = Instantiate(Resources.Load("Zhuangbei")) as GameObject;
        source = sourceobj.transform;
        sourceobj.SetActive(false);
    }

    //找到SkinnedMeshRenderer节点保存,并再play下生成新节点
    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 = target.Find("group2");

                targetSmr.Add(partName[0], partObj.AddComponent<SkinnedMeshRenderer>());
            }
             data[partName[0]].Add(partName[1], part.transform);
        }
    }

    //将选择的节点的bones  sharedMesh materials复制过去
    void ChangePart(string part, string item)
    {
        //从资料中取得各部位指定编号的 SkinnedMeshRenderer
        SkinnedMeshRenderer smr = data[part][item].GetComponent<SkinnedMeshRenderer>();

        //取得相对应名称的骨架物件来建立新的骨架列表
        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;
            }
        }
        // 更新指定部位 GameObject 的 SkinnedMeshRenderer 内容
        targetSmr[part].sharedMesh = smr.sharedMesh;
        targetSmr[part].bones = bones.ToArray();
        targetSmr[part].materials = smr.materials;
        //一般到上面就可以了,但我那模型不知道是不是我改节点弄坏了,
        foreach (Transform hip in hips)
        {
            if (hip.name != smr.rootBone.name) continue;
            targetSmr[part].rootBone = hip;
            break;
        }
    }

    public string zuojian = "zuojian";
    public string youjian = "youjian";
    public string toukui = "toukui";
    public string wuqi = "wuqi";
    //GUI只为测试,没其他大用
    void OnGUI()
    {
        if (GUILayout.Button("左肩铠甲"))
        {
            int mag = Random.Range(1, 3);
            ChangePart(zuojian, mag.ToString());
        }
        else if (GUILayout.Button("右肩铠甲"))
        {
            int mag = Random.Range(1, 3);
            ChangePart(youjian, mag.ToString());
        }
        else if (GUILayout.Button("头盔"))
        {
            int mag = Random.Range(1, 3);
            ChangePart(toukui, mag.ToString());
        }
        else if (GUILayout.Button("武器"))
        {
            int mag = Random.Range(1, 3);
            ChangePart(wuqi, mag.ToString());
        }
    }

}


demo:  https://download.csdn.net/download/weixin_41843959/10419103




猜你喜欢

转载自blog.csdn.net/weixin_41843959/article/details/80341185