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
}