换装原理中篇

换装系列文章:
换装原理初探
换装原理中篇
换装原理实践

代码复用和合并

换装原理初探中介绍了换装的核心步骤,但是只有一种男孩角色的换装,本文考虑男孩和女孩的换装。并且,对上文的一些变量命名进行调整,Target均改为Avatar,合并Model和Avatar的加载方法。其实考虑男孩和女孩的换装,主要是代码的复用和合并问题。

  • 加载Model和Avatar。由于需要复用代码,因此需要在加载方法中给出参数,这里主要有模型名字modelName,avatarName,加载存储到的变量modelTrans和avatarTrans。
  • 保存数据。同样,需要有参数,变量modelTrans和avatarTrans,参数保存容器modelData、avatarData和hips。
  • 换装。参数容器modelData、avatarData和hips,变换部位名字partName和变换型号num。

测试

为了完成上述代码的测试工作,需要定义一些测试单元,新增一个Gender变量表示男孩或女孩。

  • 在Start函数中,完成初始化测试。
  • 在Update函数中,分别完成性别切换测试和换装测试。性别切换点击鼠标左键完成,换装点击鼠标右键完成。
using System.Collections.Generic;
using UnityEngine;


public enum Gender
{
    
    
    Male,
    Female
}

public class AvatarCustomization : MonoBehaviour
{
    
    
    public Gender AvatarGender = Gender.Male;


    private Transform maleModelTrans;
    private Transform maleAvatarTrans;
    private Transform femaleModelTrans;
    private Transform femaleAvatarTrans;

    private Dictionary<string, Dictionary<string, SkinnedMeshRenderer>> maleModelData = new Dictionary<string, Dictionary<string, SkinnedMeshRenderer>>();
    private Dictionary<string, SkinnedMeshRenderer> maleAvatarData = new Dictionary<string, SkinnedMeshRenderer>();
    private Transform[] maleHips;
    private Dictionary<string, Dictionary<string, SkinnedMeshRenderer>> femaleModelData = new Dictionary<string, Dictionary<string, SkinnedMeshRenderer>>();
    private Dictionary<string, SkinnedMeshRenderer> femaleAvatarData = new Dictionary<string, SkinnedMeshRenderer>();
    private Transform[] femaleHips;

    private string[,] boyStr = new string[,] {
    
     {
    
     "eyes", "1" }, {
    
     "hair", "1" }, {
    
     "top", "1" }, {
    
     "pants", "1" }, {
    
     "shoes", "1" }, {
    
     "face", "1" } };

    private void Start()
    {
    
    
        LoadModelAndAvatar(out maleModelTrans, out maleAvatarTrans, "MaleModel", "MaleTarget");
        LoadModelAndAvatar(out femaleModelTrans, out femaleAvatarTrans, "FemaleModel", "FemaleTarget");
        SaveData(maleModelTrans,maleAvatarTrans,maleModelData,maleAvatarData,out maleHips);
        SaveData(femaleModelTrans, femaleAvatarTrans, femaleModelData, femaleAvatarData, out femaleHips);
        InitiateAvatar();
    }

    private void Update()
    {
    
    
        if(Input.GetMouseButtonDown(0))
        {
    
    
            if(AvatarGender==Gender.Male)
            {
    
    
                AvatarGender = Gender.Female;
            }
            else
            {
    
    
                AvatarGender = Gender.Male;
            }
            ChangeSex();
        }
        if(Input.GetMouseButtonDown(1))
        {
    
    
            int num = Random.Range(1, 4);
            ChangeAvatar("pants", num.ToString());
            
        }
    }

    void LoadModelAndAvatar(out Transform modelTrans, out Transform avatarTrans, string modelName, string avatarName)
    {
    
    
        GameObject model = GameObject.Instantiate(Resources.Load(modelName)) as GameObject;
        modelTrans = model.transform;
        model.SetActive(false);
        GameObject avatar = GameObject.Instantiate(Resources.Load(avatarName)) as GameObject;
        avatarTrans = avatar.transform;
        avatar.SetActive(false);
    }

    void SaveData(Transform modelTrans, Transform avatarTrans, Dictionary<string,Dictionary<string,SkinnedMeshRenderer>> modelData, 
        Dictionary<string,SkinnedMeshRenderer> avatarData, out Transform[] hips)
    {
    
    
        SkinnedMeshRenderer[] parts = modelTrans.GetComponentsInChildren<SkinnedMeshRenderer>();
        hips = avatarTrans.GetComponentsInChildren<Transform>();
        foreach (SkinnedMeshRenderer part in parts)
        {
    
    
            string[] names = part.name.Split('-');

            if(!modelData.ContainsKey(names[0]))
            {
    
    
                GameObject partGo = new GameObject();
                partGo.name = names[0];
                partGo.transform.SetParent(avatarTrans);
                modelData.Add(names[0], new Dictionary<string, SkinnedMeshRenderer>());
                avatarData.Add(names[0], partGo.AddComponent<SkinnedMeshRenderer>());
            }
            modelData[names[0]].Add(names[1], part);
        }
    }

    void InitiateAvatar()
    {
    
    
        for (int i = 0; i < boyStr.GetLength(0); i++)
        {
    
    
            ChangeStyle(maleModelData, maleAvatarData, maleHips, boyStr[i, 0], boyStr[i, 1]);
        }
        for (int i = 0; i < boyStr.GetLength(0); i++)
        {
    
    
            ChangeStyle(femaleModelData, femaleAvatarData, femaleHips, boyStr[i, 0], boyStr[i, 1]);
        }
        ChangeSex();
        
    }

    void ChangeSex()
    {
    
    
        if (AvatarGender == Gender.Male)
        {
    
    
            maleAvatarTrans.gameObject.SetActive(true);
            femaleAvatarTrans.gameObject.SetActive(false);
        }
        else
        {
    
    
            maleAvatarTrans.gameObject.SetActive(false);
            femaleAvatarTrans.gameObject.SetActive(true);
        }
    }

    void ChangeAvatar(string partName, string num)
    {
    
    
        if (AvatarGender == Gender.Male)
        {
    
    
            ChangeStyle(maleModelData, maleAvatarData, maleHips, partName, num);
        }
        else
        {
    
    
            ChangeStyle(femaleModelData, femaleAvatarData, femaleHips, partName, num);
        }
    }

    void ChangeStyle(Dictionary<string, Dictionary<string,SkinnedMeshRenderer>> modelData,
        Dictionary<string, SkinnedMeshRenderer> avatarData, Transform[] hips, string partName, string num)
    {
    
    
        SkinnedMeshRenderer part = modelData[partName][num];
        List<Transform> bones = new List<Transform>();
        foreach(var trans in part.bones)
        {
    
    
            foreach(var bone in hips)
            {
    
    
                if(bone.name == trans.name)
                {
    
    
                    bones.Add(bone);
                    break;
                }
            }
        }
        avatarData[partName].bones = bones.ToArray();
        avatarData[partName].sharedMesh = part.sharedMesh;
        avatarData[partName].material = part.material;
    }
}

猜你喜欢

转载自blog.csdn.net/Abecedarian_CLF/article/details/85051686