本文向大家介绍Unity换装原理及其简单实现
首先附上效果图:
本文的源码我将上传提供大家下载点击打开链接
实现原理:控制角色SkinMeshRenderer组件的mesh、materials、bones属性来实现角色换装
在该Demo素材中,主角是由多个网格拼接完成
其中网格对象上添加了SkinMeshRenderer组件,并指定了material、mesh、root bone
我们不采用这种方式来渲染角色
我们把角色的全部materials、mesh、bones绑定到一个SkinMeshRenderer上,其中这种做法需要注意的是materials和bones需要一一对应起来,否则渲染紊乱
好的,接下来我将写一个实例实现换装(下载参考源码方便理解)
我们Ctrl+D复制Female对象除了Female_Hips子节点保留(骨骼节点),其他都Delete
在Female节点上添加SkinMeshRenderer组件
首先随机获取到子网格
GameObject go = list[Random.Range(0, list.Count)];
SkinnedMeshRenderer goSMR = go.GetComponent<SkinnedMeshRenderer>();
if (goSMR)
{
CombineInstance ci = new CombineInstance();
ci.mesh = goSMR.sharedMesh;
ciList.Add(ci);
materialList.AddRange(goSMR.materials);
//遍历角色所有的骨骼节点来找到相对应得骨骼
GetBone(goSMR.bones);
}
其中遍历节点方式是通过节点名字来获取,将获得骨骼节点,通过遍历获得
foreach (Transform x in t)
{
foreach (Transform y in allBones)
{
if (y.name.Equals(x.name))
{
boneList.Add(y);
break;
}
}
}
最后生成角色蒙皮
mesh = new Mesh();
mesh.CombineMeshes(ciList.ToArray(),false,false);
smr.sharedMesh = mesh;
smr.materials = materialList.ToArray();
smr.bones = boneList.ToArray();
最终脚本
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(SkinnedMeshRenderer))]
public class GeneraterAvatar : MonoBehaviour
{
private enum GeneraterType
{
ALL,
EYE,
FACE,
HAIR,
PANT,
SHOES,
BODY
}
//可以供选择的对象列表
public List<GameObject> eyeList = new List<GameObject>();
public List<GameObject> faceList = new List<GameObject>();
public List<GameObject> hairList = new List<GameObject>();
public List<GameObject> pantList = new List<GameObject>();
public List<GameObject> shoesList = new List<GameObject>();
public List<GameObject> bodyList = new List<GameObject>();
//角色的SkinMeshRenderer组件上的材质列表
private List<Material> materialList = new List<Material>();
//角色的SkinMeshRenderer组件上的骨骼列表
private List<Transform> boneList = new List<Transform>();
//角色的子网格,对这些子网格进行拼接后形成角色的完整网格
private List<CombineInstance> ciList = new List<CombineInstance>();
//角色的网格
private Mesh mesh;
//角色的骨骼节点
private Transform[] allBones;
//组件
private SkinnedMeshRenderer smr;
// Use this for initialization
void Start ()
{
//获取蒙皮组件
smr = this.GetComponent<SkinnedMeshRenderer>();
//随机种子
Random.seed = (int)Time.time;
//获取各个骨骼节点
allBones = this.GetComponentsInChildren<Transform>();
//生成
GeneraterSkin(GeneraterType.ALL);
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GeneraterSkin(GeneraterType.ALL);
}
}
private void Reset()
{
ciList.Clear();
materialList.Clear();
boneList.Clear();
}
/// <summary>
/// 生成蒙皮
/// </summary>
private void GeneraterSkin(GeneraterType type)
{
Reset();
GetNextSkin(eyeList);
GetNextSkin(faceList);
GetNextSkin(hairList);
GetNextSkin(pantList);
GetNextSkin(shoesList);
GetNextSkin(bodyList);
mesh = new Mesh();
mesh.CombineMeshes(ciList.ToArray(),false,false);
smr.sharedMesh = mesh;
smr.materials = materialList.ToArray();
smr.bones = boneList.ToArray();
}
/// <summary>
/// 随机获得蒙皮
/// </summary>
private void GetNextSkin(List<GameObject> list)
{
if (list.Count > 0)
{
GameObject go = list[Random.Range(0, list.Count)];
SkinnedMeshRenderer goSMR = go.GetComponent<SkinnedMeshRenderer>();
if (goSMR)
{
CombineInstance ci = new CombineInstance();
ci.mesh = goSMR.sharedMesh;
ciList.Add(ci);
materialList.AddRange(goSMR.materials);
//遍历角色所有的骨骼节点来找到相对应得骨骼
GetBone(goSMR.bones);
}
}
}
/// <summary>
/// 遍历角色所有的骨骼节点来找到相对应得骨骼
/// </summary>
/// <returns></returns>
private void GetBone(Transform[] t)
{
foreach (Transform x in t)
{
foreach (Transform y in allBones)
{
if (y.name.Equals(x.name))
{
boneList.Add(y);
break;
}
}
}
}
}
将其挂载到Female节点上
并为其制定相对应的对象(含SkinMeshRenderer组件)
在这个重点需要提出的是:
CombineInstance ci = new CombineInstance();
ci.mesh = goSMR.sharedMesh;
ciList.Add(ci);
mesh = new Mesh();
mesh.CombineMeshes(ciList.ToArray(),false,false);
smr.sharedMesh = mesh;
该函数作用是将多个子网格进行拼接结合
本人也在寻找一份游戏开发实习工作,如果大佬们需要开发人员,请把我带走
这是我的简历:resume.liujunliang.com.cn/resume.pdf
作品的话可以私聊我哦!
==================== 即步 CSDN博客专栏=================
博客地址:http://blog.liujunliang.com.cn
个人网站:http://www.liujunliang.com.cn
==================== battle for programming =============