Hello Unity Answers! I’m having a lot of difficulty over the subject of skinned meshes, and haven’t found a suitable answer anywhere yet.
My situation is:
- I’m putting together a character
customization system with different
head, body and clothes meshes; - This will be animated using a common
skeleton; - I want this to remain in one
drawcall;
What I’ve done so far:
- I’ve managed to do this on static (non-skinned) meshes; that is, I have successfully combined the 3 meshes if they are not skinned;
- I’ve managed to create a custom atlas and change the UVs accordingly;
- I’ve tried to use SkinnedMeshCombiner ([available at the wiki here][1]) but I can’t make it work correctly;
My problems with SkinnedMeshCombiner:
- the script seems to add every bone (in all 3 exported meshes’ rigs) to the finished combined mesh. I have an AnimatorController that moves one of those rigs (avatars), so only parts of the combined SkinnedMesh move;
- if I try to edit the script around to add only one set of bones to the combined SkinnedMesh, the skin weights are all over the place and the body does not distort properly. (see [this image for the results][2] and my code below, SkinnedCharacterCombiner.cs)
Can anyone shed some light on this? Basically what I want is:
In runtime, load 3 different meshes that share the same skeleton, combine them in one SkinnedMeshRenderer, then apply animation coming from the shared rig, so that the whole character remains one drawcall.
Thanks!
SkinnedCharacterCombiner.cs
using UnityEngine;
using System.Collections.Generic;
public class SkinnedCharacterCombiner : MonoBehaviour {
void Start() {
Vector3 originalPosition = this.transform.position;
this.transform.position = Vector3.zero;
SkinnedMeshRenderer[] smRenderers = GetComponentsInChildren<SkinnedMeshRenderer>();
int numSubs = 0;
List<Transform> bones = new List<Transform>();
List<BoneWeight> boneWeights = new List<BoneWeight>();
List<CombineInstance> combineInstances = new List<CombineInstance>();
foreach(SkinnedMeshRenderer smr in smRenderers)
numSubs += smr.sharedMesh.subMeshCount;
//int boneOffset = 0;
SkinnedMeshRenderer baseMR = smRenderers[0];
for( int s = 0; s < smRenderers.Length; s++ ) {
SkinnedMeshRenderer smr = smRenderers~~;~~
~~ BoneWeight meshBoneweight = smr.sharedMesh.boneWeights;~~
~~ // May want to modify this if the renderer shares bones as unnecessary bones will get added.~~
~~ foreach( BoneWeight bw in meshBoneweight ) {~~
~~ BoneWeight bWeight = bw;~~
~~ //bWeight.boneIndex0 += boneOffset;~~
~~ //bWeight.boneIndex1 += boneOffset;~~
~~ //bWeight.boneIndex2 += boneOffset;~~
~~ //bWeight.boneIndex3 += boneOffset;~~
~~ boneWeights.Add( bWeight );~~
~~ }~~
~~ //boneOffset += smr.bones.Length;~~
~~ CombineInstance ci = new CombineInstance();~~
~~ ci.mesh = smr.sharedMesh;~~
~~ ci.transform = smr.transform.localToWorldMatrix;~~
~~ combineInstances.Add(ci);~~
~~ Object.Destroy(smr.gameObject);~~
~~ }~~
~~ Transform meshBones = baseMR.bones;~~
~~ foreach( Transform bone in meshBones )~~
~~ bones.Add( bone );~~
~~ List bindposes = new List();~~
~~ for(int b = 0; b < bones.Count; b++) {~~
~~ bindposes.Add(bones__.worldToLocalMatrix * transform.worldToLocalMatrix);__~~
** }**
** SkinnedMeshRenderer r = gameObject.AddComponent();**
** r.sharedMesh = new Mesh();**
** r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, true);**
** Material combinedMat = new Material( Shader.Find( “Diffuse” ) );**
** r.sharedMaterial = combinedMat;**
** r.rootBone = bones[0];**
** r.bones = bones.ToArray();**
** r.sharedMesh.boneWeights = boneWeights.ToArray();**
** r.sharedMesh.bindposes = bindposes.ToArray();**
** r.sharedMesh.RecalculateBounds();**
** this.transform.position = originalPosition;**
** }**
}
~~[1]: http://wiki.unity3d.com/index.php?title=SkinnedMeshCombiner**~~
~~[2]: http://dl.dropbox.com/s/di82wsw2gk7u4xm/mesh.jpg**~~