Generate skinned mesh in runtime
I want to create a script that loads character head from an external source.
I already have a character without a head, and it sits comfortably in the origin as shown here: Everything works as I expect, including animations.
Then I load mesh data from external source and add it to scene using the following code:
var character = GameObject.Find ("fuse_base_character");
var headObject = new GameObject ("head");
headObject.AddComponent<SkinnedMeshRenderer> ();
headObject.transform.SetParent (character.transform);
var headRenderer = headObject.GetComponent <SkinnedMeshRenderer> ();
headRenderer.sharedMesh = mesh;
var rig = GameObject.Find ("mixamorig:Hips");
headRenderer.rootBone = rig.transform;
Head is in exactly the same coordinate frame as the body, I can confirm that by opening both models in a 3D editor. But when I execute this code, head appears far higher than it should:
Head has exactly the same "armature" as the body, so even animations work. But head flies 3 meters above the ground instead of being in it's proper place.
I found that this happens because head uses position of the root bone as it's origin, instead of world origin! Thus it appears shifted relative to the rest of the body, because body uses world origin.
I tried to headObject.transform.Translate and headRenderer.transform.Translate, but this does not change anything. How should I add this mesh to the scene so it uses correct coordinate system? Please excuse me if the question is dumb, I am very new to Unity!
I can confirm that this is not the problem with Head model. To verify this I procedurally created a polygon whose bottom-right corner should be exactly in (0, 0, 0). When I add it to scene using the code above I end up with exactly the same situation:
As you can see, polygon location precisely matches the location of "Hips" bone.
Answer by sun_stealer · Jan 20, 2017 at 09:09 AM
Thanks to help on Unity IRC channel I managed to figure this out.
In order to add another mesh that is animated by the same skeleton you have to:
Fill "bones" array of your new SkinnedMeshRenderer object. Bones at each index should match bones that are listed in "boneWeights" array of your mesh.
Fill "bindposes" array of new mesh object. In my case I had to just copy it from body mesh to head mesh.
how did you dynamically (from code) fill the bones array and bindposes?