Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
5
Question by pixels · Jan 24, 2011 at 05:17 PM · animationskeletonskinned-meshshared

Shared skeleton and animation state

Suppose I have an animated human mesh and, as one example, a large pair of gloves that I would like to have rendering (around the actual hands) at certain times. The gloves have already been skinned to the same skeletal structure that the human model uses.

Ultimately my goal is to have the gloves mesh animate along with the human model by virtue of the fact that its mesh renderer is using the human model's bones (which are animated by the human object's animation component).

My first stab so far has been essentially the following code:

public class Equipmentizer : MonoBehaviour { public GameObject target;

void Start () { SkinnedMeshRenderer targetRenderer = target.GetComponent<SkinnedMeshRenderer>(); Dictionary<string,Transform> boneMap = new Dictionary<string,Transform>(); foreach( Transform bone in targetRenderer.bones ) boneMap[bone.gameObject.name] = bone;

 SkinnedMeshRenderer myRenderer = gameObject.GetComponent&lt;SkinnedMeshRenderer&gt;();
 for( int i = 0; i &lt; myRenderer.bones.Length; ++i )
 {
     GameObject bone = myRenderer.bones[i].gameObject;
     if( !boneMap.TryGetValue(bone.name, out myRenderer.bones[i]) )
     {
         Debug.Log("Unable to map bone \"" + bone.name + "\" to target skeleton.");
         break;
     }
 }

}

Alas the gloves still animate separately, clearly still using their own bones. After some additional testing, it seems that any assignments to elements of the mesh renderer's bones array do not actually happen. No errors though.

Is there a way to make this work, or perhaps a better approach to solving this problem? I do want to avoid saving all interchangeable skinned components out into one big asset and then hiding or showing individual meshes - this has been the only alternative suggestion I've encountered so far.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

5 Replies

· Add your reply
  • Sort: 
avatar image
16
Best Answer

Answer by pixels · Jan 24, 2011 at 08:26 PM

I've resolved this issue, so in the event that someone might find it useful in the future, I'll provide an answer here. The code I posted in the question is mostly correct; however, it seems that assigning to individual elements of the SkinnedMeshRenderer's bones array will always silently fail (more accurately, it probably succeeds at modifying the wrong data).

The solution of course was to create a new array of bones and assign it to the whole property at once. The final code looks like this:

public class Equipmentizer : MonoBehaviour { public GameObject target;

// Use this for initialization void Start () { SkinnedMeshRenderer targetRenderer = target.GetComponent<SkinnedMeshRenderer>(); Dictionary<string,Transform> boneMap = new Dictionary<string,Transform>(); foreach( Transform bone in targetRenderer.bones ) boneMap[bone.gameObject.name] = bone;

 SkinnedMeshRenderer myRenderer = gameObject.GetComponent&lt;SkinnedMeshRenderer&gt;();
 Transform[] newBones = new Transform[myRenderer.bones.Length];
 for( int i = 0; i &lt; myRenderer.bones.Length; ++i )
 {
     GameObject bone = myRenderer.bones[i].gameObject;
     if( !boneMap.TryGetValue(bone.name, out newBones[i]) )
     {
         Debug.Log("Unable to map bone \"" + bone.name + "\" to target skeleton.");
         break;
     }
 }
 myRenderer.bones = newBones;

}}

And I now have multiple meshes smoothly animating with one shared skeleton!

Also note that because the attached object doesn't use its own skeleton now, there's no sense in keeping its Animation component around.

Comment
Add comment · Show 15 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image kablammyman · Aug 05, 2011 at 06:05 PM 0
Share

thanks for this. while I cant copy your code, i will use this info to solve a problem I'm having!

avatar image Deltaflux · Aug 29, 2013 at 02:15 PM 0
Share

Thanks for that. I've been scratching my head all afternoon trying to work out why poking values into the bones array didn't work.

avatar image LudiKha · Nov 02, 2014 at 06:19 PM 0
Share

After searching for a solution for months, I can confirm this also works for me. Thanks!

avatar image Cherno · Nov 03, 2014 at 02:30 PM 0
Share

Be aware that ALL bones need to have at least one weighted vertex, otherwise they won't get exported. It's sufficient to give a bone one vertex with, say, a 0.001 weight.

avatar image christoph_r · Nov 03, 2014 at 05:02 PM 0
Share

Which is not really practicable if you have many different skinned meshes that are only affected by a few bones.

Show more comments
avatar image
4

Answer by TMPxyz · Dec 16, 2012 at 03:32 PM

Indeed, `Transform[] xxx = SkinnedMeshRenderer.bones` creates a clone of the Transform[], so without `SkinnedMeshRenderer.bones = yyy` nothing will take effect;

 void Start () {    
     SkinnedMeshRenderer targetRenderer = m_attached.GetComponent<SkinnedMeshRenderer>();
     Dictionary<string, Transform> boneMap = new Dictionary<string, Transform>();
     foreach( Transform bone in targetRenderer.bones )
     {
         boneMap[bone.name] = bone;
     }
     
     SkinnedMeshRenderer thisRenderer = GetComponent<SkinnedMeshRenderer>();
     Transform[] boneArray = thisRenderer.bones;
     for(int idx = 0; idx < boneArray.Length; ++idx )
     {
         string boneName = boneArray[idx].name;
         if( false == boneMap.TryGetValue(boneName, out boneArray[idx]) )
         {
             Debug.LogError("failed to get bone: " + boneName);
             Debug.Break();
         }
     }
     thisRenderer.bones = boneArray; //take effect
 }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image JamieD3D · Dec 08, 2018 at 06:06 PM 0
Share

This works great for me, but what is the additional step that I need to take to separate a new skinned mesh from the original?

Currently, when I destroy or hide the game object containing the original skinned mesh renderer it causes the new smr to stop animating - Its still getting data from that mesh.

avatar image
2

Answer by neoRiley · Jan 09, 2020 at 12:48 AM

Great example and thanks for the help!

I made one adjustment - in my situation, the 2nd GameObject needed bones from throughout the hierarchy so I added a method that farms all bones.

 using System.Collections.Generic;
 using UnityEngine;
 
 public class Equipmentizer : MonoBehaviour
 {
     public GameObject target;
     
     void Start ()
     {
         Dictionary<string,Transform> boneMap = new Dictionary<string,Transform>();
         GetAllSkinnedMeshRenderers(ref boneMap);
 
         SkinnedMeshRenderer myRenderer = GetComponent<SkinnedMeshRenderer>();
         Transform[] newBones = new Transform[myRenderer.bones.Length];
 
         for(int i = 0; i < myRenderer.bones.Length; ++i )
         {
             GameObject bone = myRenderer.bones[i].gameObject;
             if( !boneMap.TryGetValue(bone.name, out newBones[i]) )
             {
                 Debug.Log("Unable to map bone \"" + bone.name + "\" to target skeleton.");
             }
         }
 
         myRenderer.bones = newBones;
     }
 
 
     void GetAllSkinnedMeshRenderers(ref Dictionary<string, Transform> map)
     {
         SkinnedMeshRenderer[] renderers = target.GetComponentsInChildren<SkinnedMeshRenderer>();
         Dictionary<string, Transform> boneMap = new Dictionary<string, Transform>();
 
         foreach (SkinnedMeshRenderer smr in renderers)
         {
             foreach (Transform bone in smr.bones)
             {
                 if(!boneMap.ContainsKey(bone.gameObject.name)) boneMap[bone.gameObject.name] = bone;
             }
 
         }
 
         map = boneMap;
     }
 }
 

works great, thanks again

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image s2celerity · Jun 15, 2020 at 09:36 AM 0
Share

THANK YOU, this solved my issue of the bounding box forever expanding and staying stuck at the origin and stretching the mesh infinitely

avatar image Qwolf0521 · Sep 27, 2021 at 10:39 PM 0
Share

THANK YOU!!!! this also solved my same issue!!

avatar image
1

Answer by alwynd · Aug 30, 2013 at 02:39 PM

Dudes, I can honestly just say thank you, I have a dude, with lots of stuff, armor, weapons, clothes, all seperate fbx's, but skinned against the same skeleton, and tons of animations working with Mecanim, idle, normal and combat animations, thank you, I was almost ready to friggin give up, couldn't find a good solution for this for days, your script works perfectly, and I just didn't know how to do this, I know he needed to be reparented to a different skeleton, but when you do this in the editor, it doesn't work, because the minute the animator starts doing other animations, those meshes, even though they have been set to different root bones, still do their own thing. Thank you!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by dreamstate · Aug 01, 2012 at 11:48 PM

So I would really like to do the same thing you are talking about here but I have been messing with your script and my models for hours now and I don't get it...what should the "target" variable be? Should it be the item I am instantiating (skinned armor piece in this case)? OR should it be the main character body (and it has the full skeleton, they are both skinned to the same rig in maya exported as fbx)......any info would help at this point...or if u would be so kind as to make a small downloadable unity project that we can open and see how it is arranged Im sure many many people would find this useful...probably others have but I am somewhat new to coding so I guess that is why this isn't making sense.

Thank you very much for the code though ....cause Im sure it works, just me not getting it

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image TMPxyz · Dec 16, 2012 at 03:34 PM 1
Share

target is the main character body.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Get same Skeletal Rig movement from 3dsmax to Unity 1 Answer

animation.Play (MissingComponentException: There is no 'Animation' attached to.. 2 Answers

Loop Animation In Script? 2 Answers

Play animations to different objects 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges