Unity里的人物驱动/换装备/换武器/换衣服/卡通重定位(转)
Unity里的人物驱动/换装备/换武器/换衣服/动画重定位
刚学的过程被这个问题困扰最多。
首先,基本的,大家都知道驱动人物需要骨架、绑骨的Mesh和动画(这三个要是不知道的话就得考虑看看计算机图形学先)
然后,基本上有点maya(或其他)功底的都知道,在maya里,骨架、mesh和动画都是一种单独的存在,谁混一起谁郁闷。
在unity里面,情况也是如此,不过再复杂一点展开。
1、骨架就是transform。不像maya和理论那样,是一种实体的单独的存在。在unity里,骨架就是transform的层次关系。一个骨头就是一个transform。这个人体的骨架(Transform)组织结构一般是abdome(spine,LeftUpLeg,RightUpLeg),abdome是根(有时用hip),向上是spine(neck,LeftUpArm,RightUpArm)。这个在哪里都差不多。关键是root,就是abdome。在unity里,引用骨架都是靠它。
2、Mesh。因为Unity里的Mesh有绑骨和未绑骨两种(在哪里都差不多)。在导入资源的时候,unity会为绑骨的Mesh自动生成一个SkinnedMeshRenderer,为未绑骨的生成一个MeshFilter和一个MeshRenderer。不精细的人物,头盔、手、武器(甚至靴子)等都不用绑骨,像骑马与砍杀,只需要把armor绑骨就好。
不绑骨情况:MeshFilter负责从文件中取出真实的Mesh(这里用的是Script里的类来表示,具体可以查reference)。MeshRender负责显示。这种想要固定在人体上,其实很简单,把这个GameObject的tansform的parent设置为需要绑定的骨头的transform就好。(比如武器,transform.parent=item_l,item_l是左手一个绑定武器骨头)所以,缺点也很明显,一个mesh只能绑定到一个骨头,也就是这个mesh不会变形。(这个可以作为绑骨和不绑骨的依据,看Mesh是否需要变形,所以头盔,武器都不需要绑骨(仅在unity中成立))
绑骨情况:SkinnedMeshRenderer有俩个重要成员,一个是Mesh,一个是Bones。当然,Mesh里有每一个顶点的绑骨数据,但这里存的是序号。就是第几个骨头,并没有指明是哪个骨头,但是如果给一个根骨头就能推测出所有的骨头了。这里的Bones把所有的骨头都列出来了,至于顺序,有点扯淡,没啥规律(调试结果)。问题出来了,那SkinnedMeshRenderer里的骨头这么没顺序,Mesh里的骨头序号怎么对应过来呢?好吧,仔细想想,其实没那么复杂。因为SkinnedMeshRenderer里包含Mesh和Bones两个成员,由于都是一起生成的,那么就一个坑埋一个人,正好就对应起来了。之所以要这么个Bones列表,是因为要把它画成transform树吧。
这样就再回答一个问题,如何换装备?原SkinnedMeshRender对应的骨骼已经存在,不可能销毁它(还有其他部分要用),所以就修改SkinnedMeshRenderer本身就好。要改的有两个值(加上材质三个):Mesh和Bones。其实,原Bones根本不用变,只需要把Mesh变了就好(除非你的绑骨不是一帮人做的)。详细代码看看Unity有个官方项目。另外,我觉得吧,连SkinnedMeshRender都不用操纵,直接重新生成就好。看文章最后的代码。
动画部分最有爱。其实呢,layer这个玩意,用来分组比较合适。优先级这个特点也是可以用的,不过寄太大信心。一个layer可以设置同样的叠加方式(累加,混合),控制方式(只控制上半身)。一般不同动画都放在不同层,相同功能动画在同一层,比如向左砍人和向右砍人。另外,我们动画一般都是自己搞到的一个一个片段,如果你不是动画师,还是不要用啥累加和混合了。用一些独立的动画,让他控制身体的某些部位就好。
所以,综合看,人物控制,在unity 里,换装备,换武器都是可行的。不知道咋了,网上就是搜不到如何换装的,搞到我自己研究了好久。。。
另外,最近的新发现,升级到4后,有个mecanima模块,用来做动画重定位的,这个叫帅啊。我的以下代码没办法处理动画,因为动画之前无法重定位。但是可爱的unity的新功能来了,给每个armor和每个动画都创建一个对应的avatar,然后就直接可以用一套动画驱动所有人了(虽然表面上我们显示的是一个人,但是在内部,实现这种换装方法用的是好几个独立的人体骨骼,当然,这种方法要求每个独立的骨骼都是相同的)。
附上换装代码。
#pragma strict
public var O_body_r:GameObject;
public var O_hand_L_r:GameObject;
public var O_hand_R_r:GameObject;
public var O_helmet_r:GameObject;
public var O_calf_L_r:GameObject;
public var O_calf_R_r:GameObject;
public var O_weapon_R_r:GameObject;
public var body1_r:GameObject;
private var mBody:GameObject;
private var mHand_L:GameObject;
private var mHand_L_P:Transform;
private var mHand_R:GameObject;
private var mHand_R_P:Transform;
private var mHelmet:GameObject;
private var mHelmet_P:Transform;
private var mCalf_L:GameObject;
private var mCalf_L_P:Transform;
private var mCalf_R:GameObject;
private var mCalf_R_P:Transform;
private var mWeapon_R:GameObject;
private var mWeapon_R_P:Transform;
function Start () {
}
private var ifIs:boolean=true;
function Update () {
if(Input.GetButtonDown("Fire1")){
Generate(ifIs);
ifIs=!ifIs;
}
}
function Generate(num:boolean){
if(mBody){
Destroy(mBody);
}
if(num==true){
mBody=Instantiate(O_body_r,transform.position,Quaternion.identity);
}else{
mBody=Instantiate(body1_r,transform.position,Quaternion.identity);
}
mHand_L_P=mBody.transform.Find("abdomen/spine/thorax/shoulder.L/upperarm.L/forearm.L/hand.L");
mHand_L=Instantiate(O_hand_L_r,mHand_L_P.position,Quaternion.identity);
mHand_L.transform.parent=mHand_L_P;
mHand_L.transform.localRotation=Quaternion.Euler(0,270,90);
mHand_R_P=mBody.transform.Find("abdomen/spine/thorax/shoulder.R/upperarm.R/forearm.R/hand.R");
mHand_R=Instantiate(O_hand_R_r,mHand_R_P.position,Quaternion.identity);
mHand_R.transform.parent=mHand_R_P;
mHand_R.transform.localRotation=Quaternion.Euler(0,270,90);
mWeapon_R_P=mBody.transform.Find("abdomen/spine/thorax/shoulder.R/upperarm.R/forearm.R/hand.R/item.R");
mWeapon_R=Instantiate(O_weapon_R_r,mWeapon_R_P.position,Quaternion.identity);
mWeapon_R.transform.parent=mWeapon_R_P;
mWeapon_R.transform.localRotation=Quaternion.Euler(0,270,90);
mCalf_L_P=mBody.transform.Find("abdomen/thigh.L/calf.L");
mCalf_L=Instantiate(O_calf_L_r,mCalf_L_P.position,Quaternion.identity);
mCalf_L.transform.parent=mCalf_L_P;
mCalf_L.transform.localRotation=Quaternion.Euler(0,270,90);
mCalf_R_P=mBody.transform.Find("abdomen/thigh.R/calf.R");
mCalf_R=Instantiate(O_calf_R_r,mCalf_R_P.position,Quaternion.identity);
mCalf_R.transform.parent=mCalf_R_P;
mCalf_R.transform.localRotation=Quaternion.Euler(0,270,90);
mHelmet_P=mBody.transform.Find("abdomen/spine/thorax/head");
mHelmet=Instantiate(O_helmet_r,mHelmet_P.position,Quaternion.identity);
mHelmet.transform.parent=mHelmet_P;
mHelmet.transform.localRotation=Quaternion.Euler(0,270,90);
}
Unity里的人物驱动/换装备/换武器/换衣服/卡通重定位(转)的更多相关文章
- Unity动态换装之Spine换装
注:转载请注明转载,并附原链接 http://www.cnblogs.com/liaoguipeng/p/5867510.html 燕双飞情侣 一.动态换装原理 换装,无非就是对模型的网格,或者贴图进 ...
- DragonBones龙骨换装(局部换装+全局换装)
参考: Egret官方换装动画 Egret换装三种方式 CSDN(全局换装) egret使用DragonBones实现简单的换装 换装,主要是替换任意插槽的图片,来达到局部换装的目的. 游戏中可以只制 ...
- .NET里的行为驱动开发
BDD (Given - When - then) Ruby Cucumber, Java FitNesse , Python RoboFramework, C# specflow nspec .NE ...
- 【Unity Shaders】Unity里的雾效模拟
写在前面 熟悉Unity的都知道,Unity可以进行基本的雾效模拟.所谓雾效,就是在远离我们视角的方向上,物体看起来像被蒙上了某种颜色(通常是灰色).这种技术的实现实际上非常简单,就是根据物体距离摄像 ...
- 关于unity里pbr技术和材质 unity5默认shader和传统的对比
刚开始也不知道什么是pbr (Physically Based Rendering)后来才发现这是一种新的渲染方式 与之对应的是材质是pbs(Physically Based Shader) unit ...
- 今天抠图,Python实现一键换底片!想换什么换什么(附源码)
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 生活中我们会拍很多的证件照,有的要求红底,有的是白底,有的是蓝底,今天不通 ...
- 又双叒叕换,微软这次换Edge了
http://tech.sina.com.cn/it/2018-12-06/doc-ihmutuec6481129.shtml 其实两个月前跟一个微软的前同事聊天已经听说过微软要基于Chromiun来 ...
- Unity里的Mesh属性
----------------------------------------------------------------------------------------------- Mesh ...
- DEV GridControl TableView隔行换色/奇偶行换色
GridControl中的TableView“奇偶行换色”这件事情纠结了我好几天,虽然已经是上个月的事情,好歹记录一下吧,万一有谁要用到呢. GridControl是长这个样子的, <dxg:G ...
随机推荐
- 仿htc sense的弹性listView!
demo下载:http://pan.baidu.com/s/1ntoICdV 前一段时间换了htc m7之后,对htc的sense ui有不错的印象.特别是它的listview十分有个性.提供弹性的o ...
- Yii框架中安装srbac扩展方法
首先,下载srbac_1.3beta.zip文件和对应的blog-srbac_1.2_r228.zip 问什么要下载第二个文件,后面就知道了. 按照手册进行配置: 解压缩srbac_1.3beta.z ...
- 说说怎样管理软件日常执行的server
大家应该都有这种情况.就是软件开发时都是全力以赴的把软件开发出来.一旦软件上线执行起来我们就能松口气.从而放松了对server及数据的管理.往往这个时候.server的一个小故障都能让我们忙上好一阵. ...
- git svn 报错
删除 openjdk 时 remove 了一大堆软件. 可能由于这个原因导致使用 git svn 命令时出现类似下面的错误. sam@sam-CW65S:pics$ git svn rebase Ca ...
- MapReduce简述、工作流程及新旧API对照
什么是MapReduce? 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查而且数出有多少张是黑桃. MapReduce方法则是: 1. 给在座的全部玩家中分配这摞牌. 2. 让每一个玩家数自己手 ...
- java map 装入list
需要生成多组数据的时候,应将map时候放入循环,否则循环出来会一直覆盖之前的,只能保存一条数据. 具体如下: if (rs.next()) { do { Map<String, String&g ...
- codeforces 679e Bear and Bad Powers of 42
传送门:http://codeforces.com/contest/679/problem/E 题目意思很清晰,给你一个序列,要求你完成以下三个操作: 1.输出A[i] 2.将[a,b]区间的所有数字 ...
- dedecms中去除首页index.html的方法
本文介绍了dedecms中去除首页index.html的方法,有需要的朋友参考下. dedecms织梦cms建站程序输入地址后,而打开的实际地址后面有个index.html. 这里分享下两种解决方 ...
- 使用pt-query-digest进行日志分析
使用pt-query-digest sudo apt install percona-toolkit 也可以到官网 https://www.percona.com/downloads/percona- ...
- maven实战(6)-- pom.xml的编写
pom.xml中可以编写的东西确实挺多的,经常看到别人写的pom文件中出现了一些没见过plugin或properties等等,不知有何作用,其实很简单,只要参看maven的官方文档即可:http:// ...