unity人物模型换装系统浅析
2017-11-23 15:52
951 查看
*****最近研究了一下unity中人物模型的换装系统感觉挺有意思的!特意来分享给大家。***** 首先给大家介绍一下3D人物模型的相关知识:模型一般分为静态模型和动态模型嘛!静态模型简单的来说就是不会动的模型。那么要给一个静态模型换装是不是很简单了!只需要替换它的网格和材质就行了呗!很容易的完成一个换装。但是要是一个动态模型呢?就稍微有点复杂了哦! 我们继续来谈谈一个动态模型它的换装复杂在哪里啊!既然是动态的模型嘛!那么它首先肯定是会动的,动很容易的嘛!添加个动画就ok了啊!但是对于换装而言这一动可就容易出问题了哦!大家想啊!一个模型要它动起来,是不是需要骨骼才能让它动起来啊!有了骨骼才会有各种人物复杂的动作对吧!而这个骨骼其实就是我们在Unity3D空间中各个点的位置信息。即Transform组件。我们通过控制这些骨骼的位置信息来操作人物的各种动作。好了,模型就介绍到这里了吧!我们进入我们的主题---动态模型的换装系统。 大家先试想一下啊!我们也像替换静态模型一样,直接给模型替换材质和网格行吗?(PS:思考一分钟)原因很简单的呢!你想啊!人物模型是动态的,是通过骨骼来动的吧!如果没有骨骼了的话,可能你换了装饰,导致的结果就是动作与装饰不匹配。这样的话就会太假了!比如当你抬起一个刀剑时,准备攻击时,结果发现刀还在后面呢!这就不好了啊! 现在大概讲一下动态模型换装的思路吧!**对于一个动态模型的换装,首先我们得要有几套衣服吧!这些衣服按照部位来区分,比如:头发,头部,手,身体,脚等等。那么我们就需要一个原模型了,可以理解为一个拥有多套衣服的模型。然后我们就要对原模型进行Copy一份了。复制什么呢?当然是赋值它的皮肤骨骼和材质啦!最后给一个新的模型换上一套衣服即可!** 那么下面我们通过代码来具体实现一下:
using UnityEngine; using System.Collections.Generic; public class AvatarSystem : MonoBehaviour { //原模型,所有的可以替换的部件存储在这里 //原模型只是提供资源的作用 private Transform source; //目标骨架(骨架其实就是一系列可以运动的点的位置信息)我们在这个目标上进行换装的操作 private Transform target; //临时的源模型(中间的变量) //作为交换值使用的,没有其他的作用 private GameObject tempsource; //临时的目标骨架 private GameObject temptarget; //建立一个模型资源字典,存储对应上面的source资源 //参数 Dictionary<部位,<皮肤编号,个部位的位置信息>> private Dictionary<string, Dictionary<string, Transform>> data = new Dictionary<string, Dictionary<string, Transform>>(); //用来存储骨架上的资源信息数组 private Transform[] hips; //目标皮肤字典,替换这里面的内容就行 private Dictionary<string, SkinnedMeshRenderer> targetSmr = new Dictionary<string, SkinnedMeshRenderer>(); private Animation mAnim; //表示穿的衣服的编号 private int count = 0; // Use this for initialization void Start() { InstantiateAvatar(); LoadAvatarData(source); LoadSkeleton(); //获取到骨架上面的位置信息 hips = target.GetComponentsInChildren<Transform>(); //得到所有的动作 mAnim = target.GetComponentInChildren<Animation>(); InitAvatar(); } /// <summary> /// 实例化原模型赋值给临时的模型方法 /// </summary> void InstantiateAvatar() { //临时原模型接收加载源资源 tempsource = Instantiate(Resources.Load("FemaleAvatar")) as GameObject; //再对原资源赋值 source = tempsource.transform; //实例化出原模型并将其隐藏 tempsource.SetActive(false); } /// <summary> /// 这么多的工作只是从原模型中取出部位,然后将部位重新作为一个新的模型,之后往里面添加东西 /// </summary> /// <param name="source"></param> void LoadAvatarData(Transform source) { //安全校验一下 if ( source== null) return; //获取资源的所有皮肤存到数组中去 SkinnedMeshRenderer[] parts = source.GetComponentsInChildren<SkinnedMeshRenderer>(true); //初始化data,将资源添加到data字典中 foreach (SkinnedMeshRenderer part in parts) { string[] partName = part.name.Split('-'); //如果当前字典中没有这个对象, if (!data.ContainsKey(partName[0])) { //往字典中添加部位 data.Add(partName[0], new Dictionary<string, Transform>()); //创建一个部位 GameObject partObj = new GameObject(); //部位的名字 partObj.name = partName[0]; //设置创建的部位的父物体 partObj.transform.parent = target; //添加皮肤组件 targetSmr.Add(partName[0], partObj.AddComponent<SkinnedMeshRenderer>()); } //添加具体的部位中的皮肤编号的具体皮肤 //这样一个data中的数据才算赋值完成 data[partName[0]].Add(partName[1], part.transform); } } /// <summary> /// 加载骨骼模型方法 /// </summary> void LoadSkeleton() { temptarget = Instantiate(Resources.Load("targetmodel")) as GameObject; target = temptarget.transform; } /// <summary> /// 换装具体方法(部位,衣服) /// </summary> /// <param name="part"></param> /// <param name="item"></param> void ChangeMesh(string part, string item) { //取出衣服 获取当前需要替换的皮肤 SkinnedMeshRenderer smr = data[part][item].GetComponent<SkinnedMeshRenderer>(); //获取target上与source对应的骨骼 这里不能直接把骨骼直接赋值过去 //存放将要替换的骨骼的位置信息 List<Transform> bones = new List<Transform>(); //遍历smr中的骨骼然后和我们要替换的目标骨骼进行对比 foreach (Transform bone in smr.bones) { foreach (Transform hip in hips) { //没有找到 if (hip.name != bone.name) continue; //找到添加上去 bones.Add(hip); break; } } //进行替换皮肤,骨骼,材质 targetSmr[part].sharedMesh = smr.sharedMesh;//替换皮肤 targetSmr[part].bones = bones.ToArray();//替换骨骼 targetSmr[part].materials = smr.materials;//替换材质 } //init avatar resource //初始化换装系统的衣服数据 void InitAvatar() { //大衣 ChangeMesh("coat", "003"); //头部 ChangeMesh("head", "003"); //头发 ChangeMesh("hair", "003"); //裤子 ChangeMesh("pant", "003"); //脚 ChangeMesh("foot", "003"); //手 ChangeMesh("hand", "003"); } /// <summary> /// 绘制GUI按钮方法进行点击换装 /// </summary> void OnGUI() { if (GUILayout.Button("Head")) { if (count == 1) { ChangeMesh("head", "001"); count = 0; } else { ChangeMesh("head", "003"); count = 1; } } if (GUILayout.Button("Pant")) { if (count == 1) { ChangeMesh("pant", "001"); count = 0; } else { ChangeMesh("pant", "003"); count = 1; } } if (GUILayout.Button("Hair")) { if (count == 1) { ChangeMesh("hair", "001"); count = 0; } else { ChangeMesh("hair", "003"); count = 1; } } if (GUILayout.Button("Hand")) { if (count == 1) { ChangeMesh("hand", "001"); count = 0; } else { ChangeMesh("hand", "003"); count = 1; } } if (GUILayout.Button("Foot")) { if (count == 1) { ChangeMesh("foot", "001"); count = 0; } else { ChangeMesh("foot", "003"); count = 1; } } if (GUILayout.Button("Coat")) { if (count == 1) { ChangeMesh("coat", "001"); count = 0; } else { ChangeMesh("coat", "003"); count = 1; } } } }
效果图:
这就是一个动态换装的代码思路了,大家学会了吗?不是很难的哦!只要明白思路就很简单的啦!
小结:动态人物换装:
1.加载原模型;
2.将原模型上的皮肤存入Data中;
3.加载骨骼;
4.将Data中的皮肤取出,放入骨骼中;
5.给不同的部位实施换装。
相关文章推荐
- [Unity插件]人物换装模型换装插件
- 【Unity3d基础】Unity换装系统(1)
- Unity换装功能 Unity骨骼模型更换部件
- Unity动画系统-将A模型的动画剪辑应用到B模型上
- [资源分享][Unity][人物模型][动作]一些人物模型以及动作的分享
- [blender]把Unity的模型导入到blender中,新建拓展更多人物动作
- cocos2d-x实现3D模型的换装系统的研究
- [Unity实战]详解换装系统(三)
- 布料系统原理浅析和在Unity手游中的应用
- Unity人物换装
- Unity 换装系统
- unity人物换装
- Unity 3D Avatar换装系统 SkinnedMeshRenderer皮肤渲染
- 最好用Unity粒子系统组件主要参数浅析
- Unity换装系统设计
- cocos2d-x实现3D模型的换装系统的研究
- Unity 3D换装系统教程/Demo
- 【AS3 Coder】任务六:人物换装(纸娃娃)系统的制作
- [Unity实战]详解换装系统(四)
- [Unity实战]详解换装系统(二)