摘自http://forum.unity3d.com/threads/16485-quot-stitch-multiple-body-parts-into-one-character-quot

So I have many many models.  Each has a skeleton, material, etc.

I want to take some of these and combine them into one so I can apply animation commands to one rather than many (and so they stay in sync).

I have one mesh, say MeshA with the following hierarchy:

MeshA
-AllJoint
-AllTrans1
-Take 001
-MeshA

Take 001 being a sample animation clip
MeshA being the mesh

MeshB is similar in hierarchy however has the same bone structure (down to every detail).  MeshA is a body, and MeshB is arms.

I want to "stich" MeshB into MeshA so that I can apply animations to MeshA and have MeshB work....

Currently, I just create a base object, put MeshA and MeshB under it, and apply animations to them individually (it gets really tedious with more than just these 2, specially when the animations get out of sync or I want to do blending).

How do I "stich" these 2 together as it says in the Unity2.1 features?

Ok, here we go, finally got around to jotting a bit down!
Bones - Just a hierarchy of GameObjects.  The transforms are what the system uses Animation Clips - Collection of vectors to modify transforms.  Animation clips reference the bone by name I believe (although I haven't tested this fully, it works in my scripts).
So, you want to stitch some models together to share the bones and share an animation component.  Took me a bit to figure this out, then again I'm a bit slow
Where does the information in a model object go in Unity GameObjects? Answer is, quite simply, in the components!
When an object is updated in the Unity engine it's components interact with Unity in different ways.  If it has a MeshRenderer component, then it has geometry data to send to the rendering system.  A rigid body component would send geometry data to the physics system for simulation.  And so on......
We all know a static mesh is easier to render than a dynamic one (one where the vertices are changing all the time) as the dynamic one causes the graphics card to do more state changes and thus slows down rendering.  Although today's technology is very capable of doing this without slowing down, developers tend to take that as a queue to overload the system with regards to dynamic objects.
With that I introduce you to MeshFilters, MeshRenderers and SkinnedMeshRenderers! These are the bread and butter of the models in unity!
A static Model (procedural), which requires no animation (bone animation), would need a MeshFilter to hold the Model Geometry and a MeshRenderer to render the geometry.  Being new to Unity from 2.0 and on I can only assume this was kept this way, meaning 2 separate components, to A. Stay backwards compatible in the engine and B. Allow for compiled geometry to quickly be accessed in an organized fashion.  I believe the MeshFilter stores the geometry source whereas it sends a compiled version to the MeshRenderer upon creation.  The MeshRenderer merely adds materials, shadows, and so on based on your configuration of the MeshRenderer.
A dynamic model (non-procedural) has the combination of the MeshFilter and MeshRenderer all built into one.  It stores the source mesh, does lookups for bone structures, compiles the geometry and then stores it in it's own renderer for when Unity requires it to be rendered.
That's all great, and probably somewhat inaccurate (Hey, I didn't promise you an insiders look into the Unity engine, just a compilation of all the testing I have been doing to get my own projects off the ground in addition to my decades of experience with creating engines in C++ and so on), but how do I add one model to another in code?  Alright, enough Unity Component Theory and on to application......
Adding objects to a Static GameObject: Simply add a MeshFilter, and set the sharedMesh variable to the mesh you want.  If you want a texture on that mesh, just add a MeshRenderer and set materials of that MeshRenderer to whatever materials you want displayed (some meshes have multiple UV layers, or multi-texturing, this is set in the MeshRenderer on which material is pointing to which UV set). A link to the MeshFilter Docs: http://unity3d.com/support/documenta...eshFilter.html A link to the MeshRenderer Docs: http://unity3d.com/support/documenta...hRenderer.html
Adding objects to a Dynamic GameObject: Yeay, get ready to get dirty!  First thing of great note is that the MeshFilter and MeshRenderer of the Static Object have been combined into one great SkinnedMeshRenderer.  I will talk more about that later but for now, lets talk about bones!  So, we have a bone structure in an existing GameObject, how do we identify it?  I mean in my models I see (in some cases, but I will get to exceptions later) the following objects under the root object after I import it:
RootImportedObject -AllTrans1 -AllJoint -InfoObject (named the same as the rootImportedObject)
When I look at the AllJoint I will see more children, something like this:
AllJoint -JNT_C1_Hip01 --JNT_C1_Leg_R01 --JNT_C1_Leg_L01 -JNT_C1_Spine01 --JNT_C1_Head01 ---JNT_C1_Head02
Each one of them is named.  Ok, so that's the bone structure, I need to keep that AllJoint intact!  The AllTrans1?  Not sure what that is, it has a control object, and then all the same bone names below it in the same structure as the AllJoint.  I deleted this from my model and noticed no change in animation, so I am not sure what it is for, although I can say it is merely a hierarchy of transforms just like the AllJoint is.
The InfoObject in the above hierarchy holds the components for my SkinnedMeshRenderer and any materials used. 
Exceptions: Now I feel it important to mention exceptions to what I have found above.  The importer does it's best to create the same structure for animated assets however based on how it was exported (and from what asset creation tool, or modeler), it might slip up from time to time.  Although it doesn't affect how the animation works, or looks, it affects how the information is kept in the hierarchy.   I HAVE found the InfoObject to actually be one of the bones; where a bone, one of the children bones deep down in the hierarchy, had the SkinnedMeshRenderer and Materials components.  So in a Script, I had to do a search on the game object for ALL Components in children for SkinnedMeshRenderers in order to locate them and copy them over to the target object.
So how do the animations actually work? The answer is, as it would seem, by name.  You call the clip by name, the clip calls the bones by name, and so on.  When you run an animation in the Animation Component it does a search (when you add the component the first time) through the Object it's attached to and through all it's children to find all the bones it needs to move/rotate/transform by name.  If I remove the JNT_C1_Leg_R01 object from my hierarchy above and try to run the animations associated with this model Unity will error out with a reference somewhere along the lines of "bone differences" or something (I forget the error).  BUT I can move JNT_C1_Leg_R01 somewhere else in the hierarchy, like parent it to the spine or head, and the animation will still work (although the visual outcome will be very funky as the original hierarchy is now different than intended, and a guy that is supposed to be running might look like he's doing some funky dance instead).
Ok, so the Animation works with the bones by name, how does that correlate to the actual mesh? By a predetermined array pointing to each bone of course.  The SkinnedMeshRenderer has a Bones array built into it, you simply create an array of those transforms (the bones above) and set that bone array to it.  The skinned mesh renderer looks at the bones and their transforms and then modifies the geometry of it's internal MeshFilter.  It then compiles the geometry and sends it to it's internal MeshRenderer (remember I told you that the SkinnedMeshRenderer combined the MeshRenderer and the MeshFilter).  The Internal MeshRenderer does it's magic on it and sends it to Unity's renderer for display.
Link to the SkinnedMeshRenderer: http://unity3d.com/support/documenta...hRenderer.html
Wonderful, you told me exactly what 36 hours of reading the documentation can tell me, how do i do it already? Ok ok....  We will take MyTorso and MyArm, both animated model assets I just imported into Unity and we will go through the scripting necessary to stitch the two together.  Now remember that their bones have to be the same setup; meaning they have to have bones by the same name or the same skeleton when they are exported.
So, Drag MyTorso and MyArm on to the scene of Unity.  Lets create a script that stitches MyArm INTO MyTorso leaving us with just MyTorso to animate and what not in other scripts.

Code:  
  1. var objPlayer : GameObject;
  2. var objLimb : GameObject;

Ahhhh, that fresh code smell!  We have two Editor Refferenceable objects   Add this script to any game object (even player), and drag MyTorso onto objPlayer and drag MyArm onto objLimb.  The first thing we will need to do is to look through objLimb for our SkinnedMeshRenderer, once we find it (or them, hehe, remember we can have multiple meshes and what not on them) we will then begin the construction on objPlayer.

Code:  
  1. AddLimb( objLimb, objPlayer );
  2.  
  3. function AddLimb( BonedObj : GameObject, RootObj : GameObject )
  4. {
  5. var BonedObjects = BonedObj.gameObject.GetComponentsInChildren( SkinnedMeshRenderer );
  6.     for (var SkinnedRenderer : SkinnedMeshRenderer in BonedObjects)
  7.         ProcessBonedObject( SkinnedRenderer, RootObj );
  8. }

YEAY our first function!  I like to write independent functions so that I can easily move code from one project to another as much as possible.  So if your curious why somethings are in there that probably wont pertain to this tutorial, bare with me.
So above we send our objPlayer in as a root object (or destination object) and the objLimb's SkinenedMeshRenderer in as the target object (or our object we need to copy over).  I pass the Renderer in instead of the GameObject because we will need to re-find it to get it's info anyhow.  And since we can reference a gameObject from a component, it just seems best to pass what we are actually looking for.  You'll see that I do a search for all SkinnedMeshRenderers in the object, then iterate through each one passing it to a processbone function.  It is in that function where we will actually do the stitching, so on we go:

Code:  
  1. private function ProcessBonedObject( ThisRenderer : SkinnedMeshRenderer, RootObj : GameObject )
  2. {
  3.     /*      Create the SubObject        */
  4.     var NewObj = new GameObject( ThisRenderer.gameObject.name );
  5.     NewObj.transform.parent = RootObj.transform;
  6.     /*      Add the renderer        */
  7.     var NewRenderer = NewObj.GetComponent( SkinnedMeshRenderer );
  8.     /*      Assemble Bone Structure     */
  9.     var MyBones = new Transform[ ThisRenderer.bones.Length ];
  10.     ; i<ThisRenderer.bones.Length; i++ )
  11.         MyBones[ i ] = FindChildByName( ThisRenderer.bones[ i ].name, RootObj.transform );
  12.     /*      Assemble Renderer       */
  13.     NewRenderer.bones = MyBones;
  14.     NewRenderer.sharedMesh = ThisRenderer.sharedMesh;
  15.     NewRenderer.materials = ThisRenderer.materials;
  16. }
  17.  
  18. private function FindChildByName( ThisName : String, ThisGObj : Transform ) : Transform
  19. {
  20.     var ReturnObj : Transform;
  21.     if( ThisGObj.name==ThisName )
  22.         return ThisGObj.transform;
  23.     for (var child : Transform in ThisGObj )
  24.     {
  25.         ReturnObj = FindChildByName( ThisName, child );
  26.         if( ReturnObj )
  27.             return ReturnObj;
  28.     }
  29.     return null;
  30. }

Whoa, busy busy busy!  Two functions for the price of one!  Ok, enough cheesy references....... So what are we doing above?  We passed in the RoobObject and our SkinnedMeshRenderer from the object we want to stitch into the root. First, and because I like organization, we create an object to hold all this info in the root object.  Remember it doesnt matter where in the rootobject this info resides as long as the bones it refferences stay the same (or stay the same name/heirarchy).  K, so I create it, name it what our limb object was named (so we know what it is), and parent it to the root object (or our torso in this case). Next we add the SkinnedMeshRenderer component to our new subobject.  This will hold the same stuff our arm has with the exception of the bones being referenced from the torso object. Now we need to find the bones, by name, from the old limb object and create an array of them to insert into the new renderer.  This uses the second function above.  You can see we look through the bones of the arm, get the name of each, find them by name in the torso, and create an array based on that info.  Lastly we set the bones of the new renderer to our new bones reference array.  Set the mesh, and the materials, and BAMMMM!!!!
After this, we can run animations, move the bones around manually, or what have you and you will see the limb follow along as if it were the same mesh as the torso.
This is all I have time for now, and feel free to make any corrections to this as I don't assume this to be accurate.  I only know it works from all the testing I have done from my own projects [/quote]

unity3d由多个部分组成一个角色的更多相关文章

  1. 【浅墨Unity3D Shader编程】之中的一个 夏威夷篇:游戏场景的创建 &amp; 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨)  ...

  2. 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)

    这几篇都是我原来首发在 segmentfault 上的地址:https://segmentfault.com/a/1190000005040834 突然想起来我这个博客冷落了好多年了,也该更新一下,呵 ...

  3. Unity3D游戏开发初探—4.开发一个“疯狂击箱子”游戏

    一.预备知识—对象的”生“与”死“ (1)如何在游戏脚本程序中创建对象而不是一开始就创建好对象?->使用GameObject的静态方法:CreatePrimitive() 以上一篇的博文中的“指 ...

  4. Unity3D 中 用quaternion 来对一个坐标点进行旋转的初步体会

    在unity3d中,用四元数来表示旋转,四元数英文名叫quaternion . 比如 transform.rotation 就是一个四元数,其由四个部分组成 Quaternion = (xi + yj ...

  5. 【unity3d游戏开发之基础篇】unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子

    原地址:http://www.cnblogs.com/xuling/archive/2013/03/04/2943154.html 最近开始研究U3D,它的强大就不多说了, 今天研究了研究射线相关东西 ...

  6. Unity3d修炼之路:载入一个预制体,然后为该对象加入组件,然后查找对象,得到组件。

    #pragma strict function Awake(){ //载入一个预制体 资源必须在 Resources目录下 Resources.LoadLoad(); //载入后 必须演示样例化 Ga ...

  7. Unity3D for VR 学习(1): 又一个新玩具 暴风魔镜 4(Android)

    2016年伊始,有了VR虚拟现实硬件设备:  暴风魔镜4–好奇者的新玩具 . 2015年下半年的朋友圈中各种VR.AR的新闻层次不穷,搞的我也心痒痒的:好歹咱也是职业的Unity3D程序员,高大上的O ...

  8. Unity3D 画线插件 Vectrosity 画一个一直循环的正弦函数曲线

    直接贴代码 public Material myMaterisl; float fx;//曲线最左边的X坐标 float fy;//曲线趋于直线时y轴坐标 float fyMax = 0f;//曲线最 ...

  9. Unity3D 游戏开发构架篇 ——角色类的设计与持久化

    在游戏开发中,游戏角色占了很大的篇幅,可以说游戏中所有的内容都是由主角所带动.这里就介绍一下角色类的设计和持久化. 一.角色类应用场景和设计思想 游戏中的角色类型不一而足,有不同的技能,有不同的属性等 ...

随机推荐

  1. django自带的django.core.mail模块实现发邮件的功能

    django自带了一个模块,可以实现发邮件的功能.如果项目开发遇到需要发邮件进行验证的时候可以用到. 1.先要准备发件人 发邮件需要使用SMTP.SMTP是什么呢? 简单邮件传输协议(Simple M ...

  2. 【python】r+,w+ 全局变量

    来源:http://www.educity.cn/wenda/352188.html r+:可读可写,若文件不存在,报错w+: 可读可写,若文件不存在,创建文本模式:遇换行符时根据操作系统不同自动转换 ...

  3. jps命令学习

    jps命令学习 标签(空格分隔): jvm jps介绍 ( JVM Process Status Tool ) 网文 jps命令用于查看当前Java进程及其pid等相关信息,同ps -ef | gre ...

  4. 《java并发编程实战》读书笔记11--构建自定义的同步工具,条件队列,Condition,AQS

    第14章 构建自定义的同步工具 本章将介绍实现状态依赖性的各种选择,以及在使用平台提供的状态依赖机制时需要遵守的各项规则. 14.1 状态依赖性的管理 对于并发对象上依赖状态的方法,虽然有时候在前提条 ...

  5. Delphi使程序的窗口出现在最前面并激活

    procedure setAppFront(); //使程序的窗口出现在最前面并激活 var pt, OldPt, NewPt: TPoint; begin //判断Application是否最小化, ...

  6. hdu 5116 计数

    题目大意:给你n个点, n个点的坐标都在200以内,让你统计不相交的两个L形的种数,且L形的两条边长的gcd = 1. 思路:用二维树状数组维护点的信息,然后划分区块进行统计,题解是用总的减去相交的, ...

  7. Maven的私有仓库Nexus

    1.什么是Nexus 在前面进行maven项目的构建中,可以看到在构建的过程中需要安装maven的依赖插件,如图: 在日常的开发构建中,我们也可以自己搭建一个私有的nexus.那么什么是nexus呢? ...

  8. css文本、字母、数字过长 自动换行处理

    ---恢复内容开始--- white-space: normal|pre|nowrap|pre-wrap|pre-line|inherit;white-space 属性设置如何处理元素内的空白norm ...

  9. 关于在windows下部署发布QT程序的总结

    原文请看:http://www.cnblogs.com/javaexam2/archive/2011/05/18/2632916.html 关于在windows下部署发布QT程序的总结 2008-06 ...

  10. Flask实战第57天:UEditor编辑器集成以及配置上传文件到七牛

    相关链接 UEditor:http://ueditor.baidu.com/website/​ 下载地址:http://ueditor.baidu.com/website/download.html# ...