Unity Avatar换装原理实例

来源:互联网 发布:淘宝退款在哪里看 编辑:程序博客网 时间:2024/05/19 12:41

本文向大家介绍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 initializationvoid Start (){//获取蒙皮组件smr = this.GetComponent<SkinnedMeshRenderer>();//随机种子Random.seed = (int)Time.time;//获取各个骨骼节点allBones = this.GetComponentsInChildren<Transform>();//生成GeneraterSkin(GeneraterType.ALL);}// Update is called once per framevoid 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;


该函数作用是将多个子网格进行拼接结合



==================== 即步 CSDN博客专栏=================

博客地址:http://blog.liujunliang.com.cn  

个人网站:http://www.liujunliang.com.cn     

==================== battle for programming =============


0 0