Unity换装

来源:互联网 发布:2016年西部决赛数据 编辑:程序博客网 时间:2024/04/27 20:04

2017.11.27 

Add: 

这种方式的使用前提是:每个部分拥有自己的SkinnedMeshRenderer。

骨骼都是使用自己的骨骼,只不过需要对自己的骨骼进行筛选。


 public SkinnedMeshRenderer rend1;
        public SkinnedMeshRenderer rend2;


        private void OnGUI(){
            if (GUILayout.Button("Mode_1")){
                //rend2 使用 rend1的骨骼信息
                rend2.bones = GetBones(rend1.bones, rend2.bones);


                rend2.transform.parent = rend1.transform.parent;
                Destroy(rend1.gameObject);
            }
            if (GUILayout.Button("Mode_2")) {
                //rend1 使用自己的骨骼信息  
                rend1.bones = GetBones(rend1.bones, rend2.bones);
                rend1.sharedMesh = rend2.sharedMesh;
                rend1.materials = rend2.materials; //这种方式会多创建一个材质信息


                Destroy(rend2.gameObject);
            }
        }


        public Transform[] GetBones(Transform[] trans1,Transform[] trans2) {
            List<Transform> bones = new List<Transform>();


            foreach (Transform item in trans2)
            {
                foreach (Transform bone in trans1)
                {
                    if (bone.name.Equals(item.name))
                    {
                        bones.Add(bone);
                        break;
                    }
                }
            }
            return bones.ToArray();
        }


Former:

简略写了一下换装,基本功能可以实现,但是直接用下面的代码会有一些问题,目前还不完善。稍后会做调整,先记录一下。

主要是修改SkinnedMeshRenderer中的三个属性,并且每个可替换的部分都应该包含SkinnedMeshRenderer组件。

using System.Collections;

using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(SkinnedMeshRenderer))]
public class AvatarTest : MonoBehaviour
{
    //SkinnedMeshRenderer组件
    private SkinnedMeshRenderer smr;
    //Mesh
    private Mesh mesh;
    //角色的骨骼
    private Transform[] allBones;


    //SkinnedMeshRenderer上的材质
    private List<Material> materialsList = new List<Material>();
    //SkinnedMeshRenderer上的骨骼
    private List<Transform> bonesList = new List<Transform>();
    //角色的子网格
    private List<CombineInstance> combinesList = new List<CombineInstance>();


    void Start()
    {
        //mesh = new Mesh();
        smr = this.GetComponent<SkinnedMeshRenderer>();
        allBones = this.GetComponentsInChildren<Transform>();
    }


    /// <summary>
    /// 生成
    /// </summary>
    private void CreatSkin()
    {
        if (combinesList.Count > 0)
        {            
            // start()中声明一个Mesh()  这里调用mesh.Clear() 效果也是一样的;
            mesh = new Mesh();


            mesh.CombineMeshes(combinesList.ToArray(), false, false);


            smr.sharedMesh = mesh;
            smr.materials = materialsList.ToArray();
            smr.bones = bonesList.ToArray();
        }
    }


    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="part"></param>
    /// <param name="partObj"></param>
    public void ChangeSkinPart(GameObject partObj)
    {
        ResetSkin();


        SkinnedMeshRenderer partSmr = partObj.GetComponent<SkinnedMeshRenderer>();
        if (partSmr)
        {
            materialsList.AddRange(partSmr.materials);


            GetBonesList(partSmr.bones);


            CombineInstance ci = new CombineInstance();
            ci.mesh = partSmr.sharedMesh;
            combinesList.Add(ci);

            CreatSkin();
        }
    }


    private void GetBonesList(Transform[] t)
    {
        foreach (var item1 in t)
        {
            foreach (var item2 in allBones)
            {
                if (item2.name.Equals(item1.name))
                {
                    bonesList.Add(item2);
                    break;
                }
            }
        }
    }


    private void ResetSkin()
    {
        materialsList.Clear();
        bonesList.Clear();
        combinesList.Clear();
    }


    #region Test


    public GameObject testPart;


    void OnGUI()
    {
        if (GUILayout.Button("ChangePart"))
        {
            ChangeSkinPart(testPart);
        }
    }


    #endregion 

}