x


Get so-called "root bone" using Unityscript/c#

Note - critically, Bunny has determined that changing the field in question in the inspector, is meaningless, just an error on Unity's part. Changing that field in the inspector actually does absolutely nothing. It is a read-only value.

This is a huge finding and we should all seriously thank Bunny83 for this.

Anther triumph of the rare smart user v. utterly useless indeed missing documentation.


(Rephrasing this slightly...)

If you look in the Inspector at your SkinnedMeshRenderer, you will see the #7 item (just after Mesh and just before Bounds) is "RootBone"

Can anyone please state, using either Unityscript or c#, how to get what the Panel there refers to as the "Root Bone" of that object? As shown in the image below with red arrows. Thanks!!

As Bunny, thank God, absolutely precisely explains ...

"In [a] Mesh, a vertex can be bound to four different bones...

The bones are specified by a bone-index...

[from] the bones array of the SkinnedMeshRenderer...

[ie, the array SkinnedMeshRenderer.bones]"

So, WTF is the "Root Bone"??

Is it the 0 element of SkinnedMeshRenderer.bones, or is that naif, or what? THANKS!

alt text

exampSMRPanel.jpg (79.0 kB)
more ▼

asked Jun 17, 2012 at 01:04 PM

Fattie gravatar image

Fattie
27.4k 332 693 417

Once more ;) There is no root bone that is relevant for anything related to the SkinnedMeshRenderer. I admit i've never seen the "Root Bone" at the SkinnedMeshRenderer since our project uses Unity 3.0 and there is no such thing in the inspector.

I've just looked into the SkinnedMeshRenderer of Unity3.5 and found this:

 internal extern Transform actualRootBone
 {
     [WrapperlessIcall]
     [MethodImpl(MethodImplOptions.InternalCall)]
     get;
 }

It's an internal property which is used by the inspector to show you the root bone. As you can see it can't be set at all nor read since it's internal. I guess they implemented it to give you an easy access to the topmost bone. Anyway it's not related to the actual function of the SkinnedMeshRenderer.

*edit* the getter of that property is written in native code, but i guess it just does something like that:

 Transform root = bones[0];
 for(int i = 1; i < bones.Length; i++)
     if (root.IsChildOf(bones[i]))
         root = bones[i];
Jun 17, 2012 at 03:04 PM Bunny83

It seems it has no function at all. Just try replacing it with something else. The bones are still the same. I guess you can replace it because Unity was lazy when writing the Inspector for the SkinnedMeshRenderer. They just use Serialized Properties for everything. So if you drag something onto the "rootbone" it serializes that information, but it's never used anywhere...

I can't look behind the scenes (just the managed part ;) ) this is just what you can observe and guess.

Jun 17, 2012 at 03:30 PM Bunny83

".... It's an internal property which is used by the inspector to show you the root bone"

In Unity, what is the root bone? Is it the zero entry in .bones?

In short, when the inspector "gets" that informtaion ("to show you the root bone"), HOW DOES IT DO THAT?

Where does it look, to get that information !?!

Jun 17, 2012 at 03:41 PM Fattie
(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

I've posted it already on your other question as comment, but once more ;)

A SkinnedMeshRenderer doesn't have something like a root bone. It doesn't even care about the bone-hierarchy. The SkinnedMeshRenderer just needs an array with all bones in the order they are bound in the mesh. This reference is setup by the Mesh importer. It creates the bone hierarchy and assigns all bones to the bones array. In the Mesh a vertex can be bound to 4 different bones. The bones are specified by a bone-index. This index is related to the bones array of the SkinnedMeshRenderer.

Again, the bone-hierarchy is irrelevant for the SkinnedMeshRenderer. The hierarchy is just an automatic way for affecting subbones, but on the skinning level there are just bones.

Another important array is the Mesh.bindposes - array. It specifies the "resting position" of each bone. The example shows how to create a very very simple model with two bones.

It's almost impossible to "simply" assign a bone structure to a certain skinned mesh because you have no idea of the bones order. You can of course try to determine which bone belongs to which index by calculating the mean of all vertices that are affected by a bone. That usually gives you the approximate position of the bone, but it's not really reliable.

For imported models, the connection - information is imported by the MeshImporter and is stored in the bones array.

*edit*

Here's an example print of our player characters bone array:

 Bone index:0  Name: Bip001 R Thigh
 Bone index:1  Name: Bip001
 Bone index:2  Name: Bip001 R Calf
 Bone index:3  Name: Bip001 R Foot
 Bone index:4  Name: Bip001 L Foot
 Bone index:5  Name: Bip001 R Toe0
 Bone index:6  Name: Bip001 Pelvis
 Bone index:7  Name: Bip001 Spine
 Bone index:8  Name: Bip001 Spine1
 Bone index:9  Name: Bip001 L Thigh
 Bone index:10  Name: Bip001 R UpperArm
 Bone index:11  Name: Bip001 R Forearm
 Bone index:12  Name: Bip001 R ForeTwist
 Bone index:13  Name: Bip001 RUpArmTwist
 Bone index:14  Name: Bip001 R Hand
 Bone index:15  Name: Bip001 R Finger0
 Bone index:16  Name: Bip001 R Finger2
 Bone index:17  Name: Bip001 R Finger1
 Bone index:18  Name: Bip001 R Finger01
 Bone index:19  Name: Bip001 R Finger21
 Bone index:20  Name: Bip001 R Finger11
 Bone index:21  Name: Bip001 R Clavicle
 Bone index:22  Name: Bip001 Neck
 Bone index:23  Name: Bip001 Head
 Bone index:24  Name: Bip001 L Clavicle
 Bone index:25  Name: Bip001 Jaw
 Bone index:26  Name: Bip001 L Calf
 Bone index:27  Name: Bip001 L Toe0
 Bone index:28  Name: Bip001 L UpperArm
 Bone index:29  Name: Bip001 L Forearm
 Bone index:30  Name: Bip001 L ForeTwist
 Bone index:31  Name: Bip001 LUpArmTwist
 Bone index:32  Name: Bip001 L Hand
 Bone index:33  Name: Bip001 L Finger0
 Bone index:34  Name: Bip001 L Finger2
 Bone index:35  Name: Bip001 L Finger1
 Bone index:36  Name: Bip001 L Finger01
 Bone index:37  Name: Bip001 L Finger21
 Bone index:38  Name: Bip001 L Finger11

As you can see the first bone isn't the root bone (Bip001). It conpletely depends on how the model has been created and how the modelling software has exported the bones.

There is no general rul how you "usually" add bones to the array. It doesn't matter, it's just important that they are in the same order you used in your Mesh.

*edit*: (Let's make this answer a bit longer x) )

Here's the hierarchy of the bones, just as reference:

 Bone Hierarchy:
 Bip001
 |--Bip001 Footsteps
 |--Bip001 L Weapon
 |--Bip001 Pelvis
 |--|--Bip001 Spine
 |--|--|--Bip001 L Thigh
 |--|--|--|--Bip001 L Calf
 |--|--|--|--|--Bip001 L Foot
 |--|--|--|--|--|--Bip001 L Toe0
 |--|--|--|--|--|--|--Bip001 L Toe0Nub
 |--|--|--Bip001 R Thigh
 |--|--|--|--Bip001 R Calf
 |--|--|--|--|--Bip001 R Foot
 |--|--|--|--|--|--Bip001 R Toe0
 |--|--|--|--|--|--|--Bip001 R Toe0Nub
 |--|--|--Bip001 Spine1
 |--|--|--|--Bip001 Neck
 |--|--|--|--|--Bip001 Head
 |--|--|--|--|--|--Bip001 HeadNub
 |--|--|--|--|--|--Bip001 Jaw
 |--|--|--|--|--|--|--Bip001 Xtra01Nub
 |--|--|--|--|--Bip001 L Clavicle
 |--|--|--|--|--|--Bip001 L UpperArm
 |--|--|--|--|--|--|--Bip001 L Forearm
 |--|--|--|--|--|--|--|--Bip001 L Hand
 |--|--|--|--|--|--|--|--|--Bip001 L Finger0
 |--|--|--|--|--|--|--|--|--|--Bip001 L Finger01
 |--|--|--|--|--|--|--|--|--|--|--Bip001 L Finger0Nub
 |--|--|--|--|--|--|--|--|--Bip001 L Finger1
 |--|--|--|--|--|--|--|--|--|--Bip001 L Finger11
 |--|--|--|--|--|--|--|--|--|--|--Bip001 L Finger1Nub
 |--|--|--|--|--|--|--|--|--Bip001 L Finger2
 |--|--|--|--|--|--|--|--|--|--Bip001 L Finger21
 |--|--|--|--|--|--|--|--|--|--|--Bip001 L Finger2Nub
 |--|--|--|--|--|--|--Bip001 L ForeTwist
 |--|--|--|--|--|--Bip001 LUpArmTwist
 |--|--|--|--|--|--|--Bip001 L Shoulder
 |--|--|--|--|--Bip001 R Clavicle
 |--|--|--|--|--|--Bip001 R UpperArm
 |--|--|--|--|--|--|--Bip001 R Forearm
 |--|--|--|--|--|--|--|--Bip001 R Hand
 |--|--|--|--|--|--|--|--|--Bip001 R Finger0
 |--|--|--|--|--|--|--|--|--|--Bip001 R Finger01
 |--|--|--|--|--|--|--|--|--|--|--Bip001 R Finger0Nub
 |--|--|--|--|--|--|--|--|--Bip001 R Finger1
 |--|--|--|--|--|--|--|--|--|--Bip001 R Finger11
 |--|--|--|--|--|--|--|--|--|--|--Bip001 R Finger1Nub
 |--|--|--|--|--|--|--|--|--Bip001 R Finger2
 |--|--|--|--|--|--|--|--|--|--Bip001 R Finger21
 |--|--|--|--|--|--|--|--|--|--|--Bip001 R Finger2Nub
 |--|--|--|--|--|--|--Bip001 R ForeTwist
 |--|--|--|--|--|--Bip001 RUpArmTwist
 |--|--|--|--|--|--|--Bip001 R Shoulder
 |--Bip001 R Weapon

I've used this little script:

 public SkinnedMeshRenderer R; // assign in the inspector
 public Transform RootBone;    // assign in the inspector
 
 string ProcessBone(Transform aBone, string indent)
 {
     string result = indent + aBone.name + "\n";
     foreach (Transform T in aBone)
     {
         // Had to exclude other gameobjects since we have attached armor parts
         //Now only gameobjects are included that contains "Bip" ;)
         if (T.name.Contains("Bip")) 
             result += ProcessBone(T,indent+"|--");
     }
     return result;
 }
 
 void Start ()
 {
     Transform[] bones = R.bones;
     string text = "Bone array:";
     for(int i = 0; i < bones.Length; i++)
     {
         text += "Bone index:"+i+"  Name: "+bones[i].name + "\n";
     }
     text += "\nBone Hierarchy:\n";
     text += ProcessBone(RootBone,"");
     Debug.Log(text);    
 }

more ▼

answered Jun 17, 2012 at 01:42 PM

Bunny83 gravatar image

Bunny83
85.9k 31 169 438

Totally understood ... in short ..

"[the root bone display in the inspector is] ... is used by the inspector to show you the root bone"

Quite simply, in Unity, what is the root bone?

For example: is it the zero entry in .bones? (That is a wild guess, perhaps irrelevant.)

In short, when the inspector "gets" that informtaion ("to show you the root bone"), how does it do that?

Jun 18, 2012 at 06:11 AM Fattie

Hmm ...

have you noticed: I may be mistaken, but say you import a model, and it has a dozen or so bones. In fact, look at the example image I posted, you can see there are ten bones or so shown in the Hierarchy panel.

Note that, they appear to be in there somewhat "randomly" ... it's NOT the case that there is one highest bone with all below them in "folders". Indeed in that example the root bone has many siblings.

Perhaps I am mistaken in this ... what do you think ?

To repeat, it would appear that in terms of "the Hierarchy window, ie, the transform.parent relationships", that hierarchy (ie "the transform.parent relationship chain") is in fact NOT repeat NOT actually "the real hierarchy" of the bones ... or at any rate .. the root appears to sometimes have siblings randomly, etc

What do you think?

thus, for example, it's easy enough to make up yer own bones, and in Unity you can load them in it would apear SkinnedMeshRenderer.bones, set the boneWeights and indeed bindposes correctly on the mesh (whilst you set your uv, etc) ........ all very well BUT how or where do you set the root bone in that process?

or in fact just as you say, is it "just there" i.e. i's no big deal, what I mean is -- YOU DO NOT HAVE TO LET THE RENDER, OR ANYTHING ELSE "KNOW" -- what your "root" bone is, is that correct?

(ie, precisely as you say, one's root bone, I guess you could figure it out by noticing which one of your bones has no parent ... but in fact, again, you don't have to "tell anyone" which bone that is.

If, for some reason in your own software, you needed to use the concept of the "root" bone a lot, you'd of course just store it your own way (perhaps just what the inspector involved is doing.)

(If that is the case, the fact that the Inspector importantly Annonces which bone is the root bone with neon lights is, sort of silly and pointless. Who gives a stuff which is the root bone? How would you use that for anything anyway?)

What do you think ??

Jun 18, 2012 at 11:16 AM Fattie

Another way to look at this:

in fact, does the transform.parent hierarchy (ie, the hierarhy one sees every day in the "Hierarchy" Apple-4 window**) ... does the transform.parent hierarchy have any relationship to the bone hierarchy?

Or are they totally irrelevant to each other?

That is perhaps the basic question here. :-O

(To make an analogy .. a bit like when you make a hinge, the object hinged to the hingeholder object, is, often, also a child (ie, transform.parent hierarchy) of that hinge -- and that may or may not work for or against you in specific situations, but, there is absolutely no need for the two things to be true together.)

Thanks !!

** which, incidentally, you can resize beautifully using THIS! http://answers.unity3d.com/questions/267097/editor-programming-experts-regarding-layouts.html

Jun 18, 2012 at 11:20 AM Fattie

Ok, when you import a skinned mesh, the importer generates a Mesh asset and the corresponding bone hierarchy which it extracts from the FBX file. The importer automatically links up everything that belongs to each other. The renderer needs the complete list of bones in the exact order they have been specified.

This sounds like you have a real human arm and expect some kind of sub-D socket somewhere to plug in another arm. ;) The bones belong to the skin (Mesh).

Jun 17, 2012 at 03:35 PM Bunny83

Well, we don't know how Unity gets the root bone or if it's storing them somewhere. The property calls a native code function, so we can't see what it does, if it will cache it somewhere or not. Usually the root bone is the topmost bone when they are arranged in a hierarchy. So i would give it two criteria: It has to be a bone of that Renderer (have to be in the bones array) and doesn't have another bone as parent. That what my little code snippet does in my first comment on your question ;)

I know you don't like reading, so here's it again ;) Keep in mind, that's what i think how it works:

 Transform root = bones[0];
 for(int i = 1; i < bones.Length; i++)
     if (root.IsChildOf(bones[i]))
         root = bones[i];
Jun 18, 2012 at 09:19 AM Bunny83
(comments are locked)
10|3000 characters needed characters left

To simulate Segment Bone scaling compensation all the bones in my rig are not parented to each other (floating non hierarchy transforms) and it works just fine. Rootbone is none utilizable.

more ▼

answered Apr 17, 2013 at 01:06 AM

Shinobubu gravatar image

Shinobubu
1

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

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

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x142
x83
x23
x6

asked: Jun 17, 2012 at 01:04 PM

Seen: 3754 times

Last Updated: Apr 17, 2013 at 01:06 AM