代码复用和合并
在换装原理初探中介绍了换装的核心步骤,但是只有一种男孩角色的换装,本文考虑男孩和女孩的换装。并且,对上文的一些变量命名进行调整,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;
}
}