Search Unity

  1. Unity 2017.2 beta is now available for download.
    Dismiss Notice
  2. Unity 2017.1 is now released.
    Dismiss Notice
  3. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  4. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  5. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice

"stitch multiple body parts into one character"

Discussion in 'Scripting' started by masterprompt, Jan 6, 2009.

  1. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    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?
     
    IgorAherne likes this.
  2. Nicolaj-Schweitz

    Nicolaj-Schweitz

    Joined:
    Feb 25, 2009
    Posts:
    29
  3. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    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/documentation/ScriptReference/MeshFilter.html
    A link to the MeshRenderer Docs: http://unity3d.com/support/documentation/ScriptReference/MeshRenderer.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/documentation/ScriptReference/SkinnedMeshRenderer.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 (csharp):
    1.  
    2. var objPlayer : GameObject;
    3. var objLimb : GameObject;
    4.  
    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 (csharp):
    1.  
    2. AddLimb( objLimb, objPlayer );
    3.  
    4. function AddLimb( BonedObj : GameObject, RootObj : GameObject )
    5. {
    6. var BonedObjects = BonedObj.gameObject.GetComponentsInChildren( SkinnedMeshRenderer );
    7.     for (var SkinnedRenderer : SkinnedMeshRenderer in BonedObjects)
    8.         ProcessBonedObject( SkinnedRenderer, RootObj );
    9. }
    10.  
    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 (csharp):
    1.  
    2. private function ProcessBonedObject( ThisRenderer : SkinnedMeshRenderer, RootObj : GameObject )
    3. {
    4.     /*      Create the SubObject        */
    5.     var NewObj = new GameObject( ThisRenderer.gameObject.name );
    6.     NewObj.transform.parent = RootObj.transform;
    7.     /*      Add the renderer        */
    8.     var NewRenderer = NewObj.GetComponent( SkinnedMeshRenderer );
    9.     /*      Assemble Bone Structure     */
    10.     var MyBones = new Transform[ ThisRenderer.bones.Length ];
    11.     for ( var i=0; i<ThisRenderer.bones.Length; i++ )
    12.         MyBones[ i ] = FindChildByName( ThisRenderer.bones[ i ].name, RootObj.transform );
    13.     /*      Assemble Renderer       */
    14.     NewRenderer.bones = MyBones;
    15.     NewRenderer.sharedMesh = ThisRenderer.sharedMesh;
    16.     NewRenderer.materials = ThisRenderer.materials;
    17. }
    18.  
    19. private function FindChildByName( ThisName : String, ThisGObj : Transform ) : Transform
    20. {
    21.     var ReturnObj : Transform;
    22.     if( ThisGObj.name==ThisName )
    23.         return ThisGObj.transform;
    24.     for (var child : Transform in ThisGObj )
    25.     {
    26.         ReturnObj = FindChildByName( ThisName, child );
    27.         if( ReturnObj )
    28.             return ReturnObj;
    29.     }
    30.     return null;
    31. }
    32.  
    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]
     
    Alverik, Senshi, kaiyum and 3 others like this.
  4. Murcho

    Murcho

    Joined:
    Mar 2, 2009
    Posts:
    301
    Just tested it out, works brilliantly!
    This should be Wiki'd if possible.
    I'll be doing work with this over the next month, so if theres more findings I'll post them up.

    EDIT : In the editor, it didn't work 100%. My base bone for the limb sat on the ground and didn't move, but in the build of the scene it works perfectly, so if you have bones doing funny things in the editor make a build and double check :).
     
  5. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    Ahh, I forgot a caveat! If you're already animating the object while you add the limb, you'll have to find a way to adjust for the limb's offset after the animation started. The best rule of thumb is to stop the animation, reset the bones, add the limb, then restart the animation.

    For my application, I added a script to each major bone that records it's starting position/rotation. When a limb is added (keeping along my analogy in the previous post) I add it to the scene, then offset it locally by the offset of the bone between now and gamestart (how far it moved during animation), THEN parent it to the rootobj (torso).
     
  6. devel

    devel

    Joined:
    Mar 11, 2009
    Posts:
    140
    Hi masterprompt,

    It´s a pity that Unity doesnt offer more detailed / specific tutorials.

    Thanks a lot for this great explanations.
    I am new to Unity and your posts helped me a lot
    in understanding how things work.
     
  7. WillBellJr

    WillBellJr

    Joined:
    Apr 10, 2009
    Posts:
    397
    Excellent information - BRAVO!

    [​IMG]

    -Will
     
  8. Ony

    Ony

    Joined:
    Apr 26, 2009
    Posts:
    1,462
    Awesome, thank you! This is exactly what I was looking for and works perfectly.
     
  9. Ony

    Ony

    Joined:
    Apr 26, 2009
    Posts:
    1,462
    One question...

    Everything is working perfectly, but I'm trying to figure out how to turn off the mesh renderer for an object that's already been added via the "AddLimb" function. I have an object connected but I want to be able to turn the mesh renderer for that object on and off.

    Anyone know how to do that with this?

    ***

    Later that day...

    Well I ended up just killing the joined object and creating a new one in its place with the different pieces it needs. If someone knows of a more elegant method that would be great but for now destroy\create is working.
     
  10. AmazingRuss

    AmazingRuss

    Joined:
    May 25, 2008
    Posts:
    883
    You can Delete() the renderer, or set it's enabled property to false.
     
  11. k3ch0ng

    k3ch0ng

    Joined:
    Jan 23, 2011
    Posts:
    13
    Do youy guys have an example project with this working :) ?
     
    aquilinajake likes this.
  12. xenbiosis

    xenbiosis

    Joined:
    Jan 28, 2011
    Posts:
    49
    You are my god.
     
  13. ykk

    ykk

    Joined:
    Dec 8, 2009
    Posts:
    51
    Any example project with this working? This will helped me a lot.
     
  14. staincorb

    staincorb

    Joined:
    Mar 30, 2009
    Posts:
    113
    Hi im not a programer so I didint understand that part.

    But my question is. Do I export the character split in Diferent parts with all his diferent clothings sets all at once ?. Or Do I export Each individual piece, then combine em in unity ??

    Thx for tut think it will help me a grate bunch.
     
  15. staincorb

    staincorb

    Joined:
    Mar 30, 2009
    Posts:
    113
    Never mind I got Feed back on a nother Post.
     
  16. Demostenes

    Demostenes

    Joined:
    Sep 10, 2010
    Posts:
    1,106
    This topic was started 2009. Today is 2011 and still no decent official documentation for this from Unity documentation team. What are these guys doing?
     
  17. lakehaze

    lakehaze

    Joined:
    Mar 7, 2011
    Posts:
    24
    I don't understand this project. Why are the limbs a separate mesh from the body? Will your characters have interchangeable body-parts? Why not just make one complete character mesh, with arms and body combined in the authoring tool?
     
  18. activate_mc

    activate_mc

    Joined:
    Jun 1, 2011
    Posts:
    9
    Yes, I believe one application of this is the flexibility of changing the body parts during runtime.
     
  19. Demostenes

    Demostenes

    Joined:
    Sep 10, 2010
    Posts:
    1,106
    Imagine equipment instead of limbs.....
     
  20. kablammyman

    kablammyman

    Joined:
    Nov 22, 2010
    Posts:
    500
    agreed. The docs can use some fleshing out, and the examples can be a lot better.

    I will say that the example code masterprompt wrote works pretty well for me tho. I wrote some similar code, but i didn't get the same results as this example did. Some of the things i do work better for me, and other things, masterprompt's code works better...but I'm not sure why...the code seems to want to do the same things.

    With that said, there's something with the animation system that i still dont grasp. i wish i could "see" more of the data that unity uses...it would really help alot instead of trying to guess. Also, better docs would help too!
     
    Last edited: Aug 6, 2011
  21. Fufurata1234

    Fufurata1234

    Joined:
    Jun 6, 2009
    Posts:
    45
    I've made translation of masterprompt's script to C# and created an action for PlayMaker. If you remove PlayMaker specific tags, it could be used as sole c# script, as well.
    To use this script as PlayMaker's action, first install PlayMaker and then put supplied script into "PlayMaker\Actions" folder. After that the action (Stitch Skeletal Meshes) will appear in GameObject group.
    And of course, all credits go to masterprompt. Thanks man.
    Enjoy: http://www.multiupload.com/YILI6SI5LM
     
    Last edited: Aug 11, 2011
  22. diablo

    diablo

    Joined:
    Jan 3, 2011
    Posts:
    736
    I wrote a generic Skinning solution that is similar to the Character Customization demo but goes much further and is much easier to use. With it your able to easily switch between body-parts or skins, it optimizes the final mesh merging materials/shaders to their most optimal via atlas usage (which decreases draw-calls considerably) and it also allows you to hide certain body-parts for those games where your character loses a limb. I'm very close to publishing it on the asset store but I just want to make sure I have everything tweaked just right.
     
  23. balazs

    balazs

    Joined:
    Mar 1, 2012
    Posts:
    2
    Would you mind sharing it? :)

    Thx
     
  24. Mr.T

    Mr.T

    Joined:
    Jan 1, 2011
    Posts:
    546
    Hi this is masterprompt's invaluable code in its entirety. I need some help in understanding his FindChildByName() function. IF someone who understands this code can help in the form of some valuable comments at the locations I have pointed, the help would me much appreciated. Thanks in advance

    Code (csharp):
    1.  
    2. var objPlayer : GameObject;
    3. var objLimb : GameObject;
    4.  
    5. AddLimb( objLimb, objPlayer );
    6.  
    7. function AddLimb( BonedObj : GameObject, RootObj : GameObject )
    8. {
    9.     var BonedObjects = BonedObj.gameObject.GetComponentsInChildren( SkinnedMeshRenderer );
    10.     for (var SkinnedRenderer : SkinnedMeshRenderer in BonedObjects)
    11.     ProcessBonedObject( SkinnedRenderer, RootObj );
    12. }
    13.  
    14. private function ProcessBonedObject( ThisRenderer : SkinnedMeshRenderer, RootObj : GameObject )
    15. {
    16.     /*      Create the SubObject        */
    17.     var NewObj = new GameObject( ThisRenderer.gameObject.name );
    18.     NewObj.transform.parent = RootObj.transform;
    19.  
    20.     /*      Add the renderer        */
    21.     var NewRenderer = NewObj.GetComponent( SkinnedMeshRenderer );
    22.  
    23.     /*      Assemble Bone Structure     */
    24.     var MyBones = new Transform[ ThisRenderer.bones.Length ];
    25.     for ( var i=0; i<ThisRenderer.bones.Length; i++ )
    26.         MyBones[ i ] = FindChildByName( ThisRenderer.bones[ i ].name, RootObj.transform );
    27.  
    28.     /*      Assemble Renderer       */
    29.     NewRenderer.bones = MyBones;
    30.     NewRenderer.sharedMesh = ThisRenderer.sharedMesh;
    31.     NewRenderer.materials = ThisRenderer.materials;
    32. }
    33.  
    34. private function FindChildByName( ThisName : String, ThisGObj : Transform ) : Transform
    35. {
    36.     var ReturnObj : Transform;
    37.    /*- ---->WHAT IS HE DOING HERE?<------------ */
    38.     if( ThisGObj.name==ThisName )
    39.         return ThisGObj.transform;
    40.      /*- ---->WHAT IS HE DOING HERE?<------------ */
    41.     for (var child : Transform in ThisGObj )
    42.     {
    43.         ReturnObj = FindChildByName( ThisName, child );
    44.         if( ReturnObj )
    45.             return ReturnObj;
    46.     }
    47.     return null;
    48. }
    49.  
     
    Ony likes this.
  25. Berenger

    Berenger

    Joined:
    Jul 11, 2012
    Posts:
    76
    Thanks Mr T for showing me that thread, that was exactly it !

    As a reward, I made an example scene of how to use the masterprompt's code and commented the lines you're asking about.

    [Edit] I added the code to the wiki. There small changes, I took all the relevant code and put it in a static class instead of inside the monobehaviour. I didn't update the package below though.
     

    Attached Files:

    Last edited: Apr 3, 2012
  26. Mr.T

    Mr.T

    Joined:
    Jan 1, 2011
    Posts:
    546
    Thanks a lot f or that. I understand that last part of the code I needed to understand now :)
     
  27. poboczny

    poboczny

    Joined:
    Sep 25, 2010
    Posts:
    520
    This is beautifull in JC ! :)

    1. Can I do the same with prefabs stered somewhere in Assets ?
    2. How can I name properly the new created and rendered object ?
    3. How can I find the new created object and destroy it ?
     
  28. hike1

    hike1

    Joined:
    Sep 6, 2009
    Posts:
    401
    quote
    File Type: unitypackage SwitchEquipment.unitypackage (435.2 KB, 381 views)
    unquote

    This contains 3ds max files, not everyone has 3ds max.
     
  29. Berenger

    Berenger

    Joined:
    Jul 11, 2012
    Posts:
    76
    Quite right. Here it is with FBX instead. And a bit of cleaning.

    The attachment is not working for some reason ... So here you go : http://dl.free.fr/tf70jfu5X
     

    Attached Files:

    Last edited: Nov 20, 2012
  30. Sylker

    Sylker

    Joined:
    Sep 22, 2012
    Posts:
    10
    Sup guys?

    This is a quite awesome thread. Thanks Masterprompt, Mr .T., Berenger and everyone who have contributed to it.

    I just started messing up with this kind of character composition and I was wondering how it will gonna work with the Unity4 and Mecanim/Avatar system.

    Is it going to work the same way discussed here?
     
  31. korotkevich.md

    korotkevich.md

    Joined:
    Jun 10, 2011
    Posts:
    21
    Thanks for all for this useful script.
    But I have a problem with use of it. Clothing mesh is severly distorted after wearing (please, see pictures).
    [​IMG]
    Before wearing
    [​IMG]
    After wearing
     
    Last edited: Jan 25, 2013
  32. FernandoRibeiro

    FernandoRibeiro

    Joined:
    Sep 23, 2009
    Posts:
    1,362
    Hey, not really took a look at the code, but try to have both cloth and body at position 0,0,0. This deformation might be consequence of the actual cloth position
     
  33. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    Wow, I really had no clue this thread would get this far (personal record). Thanks to everyone who has contributed!

    I've been getting a few private messages (which unity forums are terrible in delivering to my inbox of email), so I'll cover a bit more. Forgive me for not reading what I wrote in the past, I hate reading my previous work (I always feel I was less informed, and more erroneous).

    Bones:
    These are just transforms, nothing more. The names of these transforms, in unity, are important.

    SkinnedMeshRenderers:
    These little guys are like MeshRenderers (vertices, triangles, uv) except they contain hard references to the bones. When rendered, each vertex calculates it's position in relation to the bone it references. (remember, a bone is just a transform).

    Skeleton:
    A hierarchy of bones. The names of each bone are important and should be preserved as the hierarchical paths are also important (named path to each bone, bone by bone).


    Why would someone want to stitch together models in unity?
    Well, in our case (as it was years ago, and we no longer work with that project) we wanted to have an avatar that could change clothes.

    Why not just parent clothing onto a skeleton or base model?
    Because the clothing wont move with the bones.... The only solution to this that doesn't involve stitching models together is to have a segmented skeleton, which is very 1995.

    Can't I just move the GameObject with the SkinnedMeshRenderer to be a child of the skeleton?
    Nope! Reason is because the bones that the skinnedmeshrenderer knew about are not (although named the same) the bones of this skeleton you just moved it onto. It's all about referencing.

    Why, after I use this stitching method does my clothing appear in weird places and not on the skeleton as it should?
    There are many reasons... We had lots of trouble in the art pipeline on this issue. We would stick a pair of eyes on our avatar and notice they were rotated and positioned way the hell off in NoWheresVille (it is a real place Virginia! Anyone?? no.... ok, moving on).

    To understand why this happens, you must understand what's going on with the bone references and vertices.
    1. When you create a model (with bones) which has vertices, triangles, and UV, and then you export it; The vertices are positioned in relation to the bone, at that point in time. So, it's best to have your skeleton in a TPose when your creating your assets. Also, best to have the skeleton's base animation be a few frames of that TPose. Export the skeleton in that TPose, and export the asset (groucho pants (shorts? dress?) from here on out, why? Cause I told my daughter they look terrible on her and she continues to wear them to annoy me....)

    2. When you stitch the model onto the skeleton in unity, you need to reset all the bones to their position/rotation of the TPose. Then you do the stitch (which puts the asset in the proper position/rotation in relation to the bones) and then you put all the bones back to where they were before you did the stitch so that the animation can continue as if nothing happened.

    It's worth noting that if something changes on the skeleton between when you originally exported the skeleton to when you exported the asset (or the export settings are different) then you will also get weird scaling results.

    Also worth noting: The import settings for both the skeleton and grouchos (clothing) must be identical (including import scale). Once imported, you can rescale them as a prefab or scene object till your heart's content, the clothing asset will adapt itself to the skeleton's scale.

    What's an easy way to reset the bones, stitch, then revert the bones back again?
    Glad you asked (your such a curious little scamper)!

    When the skeleton is brought into the scene, I have a script (somewhere on the root object) create a catalog of the hierarchy and each bone's name, position, and rotation (locally);

    So, a simple custom class like this:

    Code (csharp):
    1.  
    2.     public class Bone
    3.     {
    4.         #region Fields
    5.         //  I like to store as much info as I can for later use
    6.         public string name;
    7.         private Transform transform;
    8.         private Vector3 localPosition;
    9.         private Quaternion localRotation;
    10.         private Vector3 localScale;
    11.         private List<Bone> children = new List<Bone>();
    12.         #endregion
    13.  
    14.         #region Constructors
    15.         /// <summary>
    16.         /// We use the constructor to map the current state of the bone, and it's children, recursivly
    17.         /// </summary>
    18.         /// <param name="transform"></param>
    19.         public Bone(Transform transform)
    20.         {
    21.             this.transform = transform;
    22.             name = transform.name;
    23.             localPosition = transform.localPosition;
    24.             localRotation = transform.localRotation;
    25.             localScale = transform.localScale;
    26.             foreach (Transform child in transform)
    27.                 children.Add(new Bone(child));
    28.         }
    29.         #endregion
    30.  
    31.         #region Restoration
    32.         /// <summary>
    33.         /// Restore all bones to mapped state
    34.         /// </summary>
    35.         public void Restore()
    36.         {
    37.             transform.localPosition = localPosition;
    38.             transform.localRotation = localRotation;
    39.             transform.localScale = localScale;
    40.             foreach (var child in children)
    41.                 child.Restore();
    42.         }
    43.         #endregion
    44.  
    45.     }
    46.  
    Then, on awake, I create a map of the bones as they are now (which should be TPose):

    Code (csharp):
    1. var hierarchyOnStart = new Bone(this.transform);
    When I'm about to stitch a clothing asset onto the skeleton I do these steps:

    1. I create a catalog of the bone hierarchy:

    Code (csharp):
    1. var hierarchyOnStitch = new Bone(this.transform);
    2. I reset the bones to their awake state (should be TPOSE)

    Code (csharp):
    1. hierarchyOnStart.Restore()
    2. I do the stitch (using the script you all so graciously documented earlier)

    3. I restore the bones back to just before the stitch (so any animation I'm playing continues on as though nothing happened)

    Code (csharp):
    1. hierarchyOnStitch.Restore()

    And walaa!

    I kinda lost track of where I was going with this..... I tend to do that. I'll try to monitor this thread closer I guess if anyone needs help. Bare in mind that I haven't worked on this project in years (2010) and although I still fully understand the concept, may have old age creeping into my memory!
     
    kaiyum likes this.
  34. Jax_Cavalera

    Jax_Cavalera

    Joined:
    Jul 22, 2013
    Posts:
    44
    Just a quick thought and this may be way off track or not correct :

    Wouldn't it also be possible to do the following -

    1. You have a fully rigged character you want clothes to fit onto in T-Pose in say Blender
    2. You import your clothing item into the Blender project and position it so it looks right on the character.
    3. You set Automatic Weight Mapping to that item of clothing so it will now deform with the same bones at the same speed and direction as the actual player mesh beneath them.
    4. Export the clothing item now it has weight mapping data on it's vertices in .Blend (so probably a Save As.
    5. Load the clothing item into Unity and position it over your character in T-Pose or just over the character

    6. (this is the bit I'm unsure about) Tell the character bone rig to also modify the clothing item. Since the mapping on the clothing vertices will already be there.. it would technically manipulate it flawlessly as seen in Blender.

    OR an alternative 6.

    You would Save the clothing item with the player skeleton but delete the player mesh so it's just the clothes being manipulated by the skeleton now.

    Then you make a small bit of code that locks the clothes skeleton to the same position as the character skeleton's position scale and rotation. and yeah.. the clothing should snap and scale to work for any player mesh at this point so long as they are based off the same skeleton rig.and the player mesh isn't a female vs male.. because clearly a male T-shirt wouldn't fit on a female mesh.. without having 2 beams stabbing through the front of the garment, unless Unity has cloth simulation as a function you can apply to meshes so they respect collisions.
     
  35. Rico21745

    Rico21745

    Joined:
    Apr 25, 2012
    Posts:
    410
    I'm currently looking at the best way to do character customization and stumbled onto this post. I understand the general idea I think, you're basically grabbing the "part" skinned mesh renderer and stitching it onto the existing character and then remapping the bones so they point to the new piece for animation, right?

    What I'm wondering, since I haven't tried it yet, does this leave you with duplicate bones inside the character transform? LIke if the character has a Leg1 bone and you add in a Leg to it which also has a Leg1 bones, do you end up with Character -> Leg1, Leg1 in your transform hierarchy? Would it be safe to remove one of them to keep it clean if that's the case?
     
    Last edited: Sep 20, 2013
  36. Mr.T

    Mr.T

    Joined:
    Jan 1, 2011
    Posts:
    546
    I noticed recent activity in this thread while looking for something else. Glad that this is helping lots of other people like it did for me.

    Being by no means an expert on this, the one small tip I can offer to those people getting distorted meshes is to make sure that the script is attached to right bone in the hierarchy.

    I use Blender for my modelling/rigging and I did experience this problem and it was solved after trial and error by finding the right bone along the rig/skeleton hierarchy to attach this script to.

    EDIT: BY script I mean Berenger's script here
    http://wiki.unity3d.com/index.php?title=SkinnedMeshTools
     
    Last edited: Sep 23, 2013
  37. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    4,862
    I suspect it's a case of "be careful in the art pipeline/blender"... but how do you make sure the meshes don't have a gap between the torso and arm (in this case)?

    is it "best" to start from the tpose complete model and delete all but the "arm" and model the alternate arm asset from there? can you lock vertices in blender so they can't be moved so you know the edge loop of the arm and the edge loop of the torso where they meet are going to double up exactly?

    from what I've understood of the code posted there isn't anything done to merge the two meshes, they are just "butted up so close you can't tell" during the animations?
     
  38. E2R_Ben

    E2R_Ben

    Joined:
    Oct 30, 2009
    Posts:
    138
    Hi, Im an artist trying to set this up in unity 4, with Mechanim.
    So I have meshes in 3ds max: A body, shirt, jeans, hair, and shoes. Each has their own skin modifier, skinned to a standard max biped.

    Q1: Do I export (as .FBX) each piece with the skeleton rig? Or just one part (ie the body) and the rest

    Q2: How do I tie this in with the mechanim system?

    My previous solution was to export all the bits in one fbx and to turn off the parts i didnt want, but id like to sell it on the assest store in many parts now and need to separate it out into multiple fbxs. I also think one massive fbx with hidden things is not going to be as efficent.

    Thanks!
     
  39. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    Ok, it's worth noting:
    Bones don't point to vertices, its the other way around. A vertex is mapped to a bone. Bones' have no knowledge of anything. They are just dummy transforms.

    The animation knows the name of the bones, but doesn't know about the bones. The animation doesn't know about the vertices either.

    At some point (update loop? fixedupdate? not quite sure when):
    1. Animation references the bones by name
    2. Animation animates the bone transforms based on the keyframe information and time.

    When the renderer is called to render the skinned mesh, the following happens (from what I can tell):
    1. Skinned mesh renderer already has references to the bones for each vertex, so it simply offsets the vertex (local position and local rotation) to the bone transform.
    2. Weighting is applied (if available)
    3. Vertices are batched together and send to the gpu

    So Jax_Cavalera, you can see that the rig really knows nothing about the mesh. The mesh is required to hold references to the rig (and only that rig). To dedicate the mesh to a different rig, one must go through each vertex of the mesh (skinned mesh renderer) and re-assign the correct bone one wants the vertex to follow.

    The animation is a whole different part of the process. The animation is just a scripted set of position/rotations for the bone transforms. That's all the animation does. It's up to the skinned mesh renderer to know what bones to map it's own vertices to. Always remember, the bones are just dumb transforms with no knowledge of anything.

    - Bone is just an empty transform
    - Animation simply modifies bone position/rotation (based on bone name, all it knows is the bone's name)
    - Skinned Mesh Renderer moves the vertex to it's normal position, offset by the bone's (remember the animation has already acted on the bone before this point) current position/rotation (it has a hard reference to the bone itself, it got the reference on Awake by getting the bone name from the mesh filter for that vertex, then looking up the bone by name (same way the animation does it) then holding that bone as a reference for the remainder of the object's life).

    Example:
    I have a character's naked body, with rig, on model A
    I have character's shirt, with rig, on model B.

    I import A into the scene.
    I import B into the scene. I then use a script to go into the skinned mesh renderer of B, I look at all the bones it knows about (B's bones), get each bones name, then look up that same named bone in A. I then replace the reference to B's bone (by name) with the bone I found in A (by name). Then, I move the object with the skinned mesh renderer over to the heirarchy for A. I am now free to delete all of B if I want, case the mesh is now not only tied to A, but all the bones it knows about are on A.

    Whenever you stitch a different skinned mesh renderer onto an existing rig (in unity) you usually replace the hard references of the bones with the bones of the existing rig in the scene. This allows you the freedom of deleting the original bones the skinned mesh renderer was referencing (since no one knows about these bones anymore as they are all only interested in the bones you just told them to be interested in).

    You are correct. There is no actual 'merging' of the two meshes, they are simply butted up to each other. Merging of 2+ meshes is out of the scope of this technique as it's merely a stitching of meshes together rather than a melding of them. in many cases, an artist must be aware of this when creating the assets as so they stitch properly. One could use an example of putting a teddy bear's arm onto a beanie baby's body. If the parts weren't designed to stitch together seamlessly then there will be artifacts.

    A1: Yes, each piece must be exported with the rig otherwise, when imported into unity, there will be no importing of the rig, and no skinned mesh renderer will be created for that piece of clothing (just a regular, boring, old mesh renderer). From there, you are free to use the technique to move the information of the clothing piece to a new skinned mesh renderer, and remove the unused rig that it was formally attached to from the scene.

    A2: Remember, mechanim, just like the legacy animation system, only works with the transforms (bones). It doesn't work with the mesh in any way. The mesh forms itself to the bones (transforms) during the rendering phase. Mechanim has no knowledge of the mesh. It's only a bone animator.

    Hiding the pieces you dont want is in-efficient as the materials for those renderers are still loaded into the gpu (even if the vertex/triangle data isnt). Not to mention the vertex/triangle data is kept in memory when it doesnt need to be.
     
  40. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    442
    This thread is freaking awesome, much props to masterprompt. I was using the multiple meshes attached to a single skeleton, then hiding the sub meshes. This method seems SOO much cleaner and better. Going to give this a whirl tonight. Thanks for taking the time to write all the detailed write ups masterprompt!
     
  41. bawenang

    bawenang

    Joined:
    Aug 18, 2012
    Posts:
    83
    Hi, sorry if I bumped into this old thread. But I just have to ask, is there any better way to do this? Not to say that this is not already awesome as it is. But I found that it's a bit expensive in the file size part. Because each equipment will have a full set of skeleton. Which is not exactly an ideal solution for my mobile game. Thanks in advance.
     
  42. mattockman

    mattockman

    Joined:
    Feb 18, 2014
    Posts:
    118
    Looks good but there is a lot I do not understand. Can anyone offer a really basic, step by step guide on how to do this from model in blender to implementation in unity? I know it's asking a lot but I haven't found a beginner's guide anywhere on the web. This and other sites assume quite a high level of unity programming knowledge.

    If this is too much of an ask, what would I have to study in order for this information to make more sense? (I have already spent a year studying programming so I'm OK on that side of things. Using Unity methods are not so straightforward though and I find the manual cryptic to say the least).
     
  43. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    I know this thread is old, but if someone wanted to offer up a few models (say a skeleton and 1 or 2 pieces of clothing with skeleton) I'd gladly make a video and/or example project out of it.
     
    dmonin, Ony and mattockman like this.
  44. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    If you're after a rigged, animated character with some separate clothing, I think the free UMA package on the asset store could provide that (though I guarantee nothing).

    I'm still relatively new to working with this stuff, so I thought I'd ask you a question of my own if that's alright.
    I understand how the stitching works and how and why the code provided so far does what it does.
    I was wondering, however, if there was a clean, efficient way of stitching on something with a different skeleton.
    For example, say I have a basic human character with the expected skeletal structure. If I decided that, at runtime, I wanted to remove one of his arms and replace it with a mess of tentacles, could I do that?
    The arm tentacles would obviously need a different skeleton than a human arm, as well as different animations when performing the same tasks.
    I'm exceptionally tired right now, but at the moment the solution I can think of would be to keep it separate, not stitched, parented to the shoulder (or other relevant bone) and send animation commands to it when I need to.

    Would it be possible to wrangle something like this with Unity, say using Mecanim? If it were possible somehow, what about using animation layers to mask off the arms from the torso for the separation of animations?
    I greatly apologize for the rambling questions and I'm sure I'll wince at this post after I've had some sleep, so thanks for reading and for any light you might shed on the matter. =)
     
  45. mattockman

    mattockman

    Joined:
    Feb 18, 2014
    Posts:
    118
    I would be happy to. I just hope the model fits your specifications. I have a basic low poly model. I made the clothes by selecting the chest area (or legs, etc), duplicating it, and then separating it. The separated object has the same vertex groups as the original model. Do you need the clothes to be completely separate without any connection at all to the model's armature?
     
  46. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    3,736
    I'm no expert, but I think giving a character wings on their back would be a similar thing to the tentacle.

    My guess is the tentacle or wings would be a separate game object that is attached much like a sword or a hat. They would need separate animations. If you were using UMA, I guess you could attach the tentacle as a slot in place of the arm mesh, but don't weight it to the UMA bones. Create new bones for the tentacle and animate those.

    Beats me if that would work, but that's what I would try.
     
  47. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    Aye, that's what I figured and what I plan to try. When I tell my character to perform an action, I send the same command to everything in the character hierarchy that has an animation. If the receiver has an animation that matches the request, it plays it. I don't actually use UMA, so no need for me to worry about that stuff. =P
     
  48. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    I would be inclined to agree!
     
  49. masterprompt

    masterprompt

    Joined:
    Jan 6, 2009
    Posts:
    114
    I would need:
    • A skeleton with some basic animation where clothing would have to conform to (arms moving or legs moving).
    • 2 clothing models (like 2 shirts) rigged to the same skeleton (no animation needs to be with these files, just the skeleton).
    I can create a sample project and throw it up on github if need be for everyone to pull from :)
     
  50. mattockman

    mattockman

    Joined:
    Feb 18, 2014
    Posts:
    118
    That would be awesome. Here you go: http://www.pasteall.org/blend/33386

    It's not a great model but hopefully it can be tweaked to fit your purposes.
     
    Last edited: Dec 18, 2014