Before upgrading to 3.4.1f5, I was combining meshes (by script) perfectly fine, taking several mesh prefabs, and assembling it to one unified skeleton.
I didn’t change this script since last year. Now I downloaded 3.4.1f5, and anytime I’m trying to assign the SkinnedMeshRender.sharedMesh with the combined mesh, it puts this error :
I triple-checked if it was true, and it wasn’t :
I thought it was from a prefab connection loss from patching, so I completely rebuilt my Meshes Skeleton prefabs from scratch since then, but nothing has changed, I still get the error.
Also :
I’m assigning a static list of bones to my SkinnedMeshRenderer, all picked inside my universal skeleton’s transform hierarchy
I’m completely rebuilding the combined mesh bindposes and boneweights for it to fit with this list of bones
For short I’m totally forcing everything related to bindposes around that precise SkinnedMeshRenderer number of bones. So I quite don’t understand why I’m suddenly getting this error (reminder : it worked perfectly fine before the 3.4.1f5 patch)
I can see that there were a number of crashfixes concerning skinned meshes in the latest release notes, is it related ?
When I’m calculating the number of different bone indexes of the combined Meshes from its boneWeights table, it sums 43. Before 3.4.1f5, it was summing 48. Which means that now, CombineMeshes() does remove duplicated bones inside the combination.
I filed a bug report about that long ago, so it’s kind of positive. Before 3.4.1f5, CombineMeshes was just adding bones to a list of indexes, one after the other, even if one was already in that list.
The downside is that now that it cleans them, I can’t find a way to remap the bones structure to my new combined mesh, as I don’t have a way to trace their name anymore (before I just put each name of each bone of each mesh to combine inside a list, following the logic of the CombineMeshes() bones management).
How are we supposed to know which bone is corresponding to each BoneWeight.boneIndex0/boneIndex1 now ?
Something along these lines perhaps? Warning : this is off the top of my head, not tested
List<string> allBones; // this is a list of all bones across all meshes, in the order in which the meshes are going to be combined
int[] boneIndexMap = new int[allBones.count];
Dictionary<string, int> boneToUniqueIndexMap = new Dictionary<string, int>();
int uniqueBoneCount = 0;
for (int i=0; i<allBones.Count; i++)
{
string bone = allBones[i];
int originalBoneIndex;
if (boneToUniqueIndexMap.TryGetValue(bone, out originalBoneIndex))
{
boneIndexMap[i] = originalBoneIndex;
}
else
{
boneToUniqueIndexMap.Add(bone, boneIndexMap[i] = uniqueBoneCount++);
}
}
Now you have a way to map boneWeight.boneIndexX to the correct index. For example :
int actualBoneIndex1 = boneIndexMap[boneWeight.boneIndex1];
Thanks for your help Diablo. This is approximately what I was doing already by adding each bone to a List.
This was what helped find the name of bones by index with a reverse index reference Dictionary.
Problem is that now, CombineMeshes() seems not to add bone indexes in the absolute order where they are combined anymore.
I’m investigating it right now, keeping you in touch if I find something.
Ok something’s gone terribly wrong with CombineMeshes() it seems.
I’ve made a simple test :
combine several meshes, all pointing to different parts of a unique skeleton (ex : head pointing to 5 bones, arms → 10 bones, torso → 4 bones, etc).
without any further treatment, taking the combined mesh as it is generated from Unity, then counting the number of different bone indexes in boneWeights (simply by adding boneWeights’ boneIndex0/1/2/3 to a list if this list doesn’t already contain it)
then count the number of bindposes of the combined mesh
----> Result is that for some combinedMeshes, the number of generated bindposes is not the same as the number of generated bone indexes from the list. Hence the unexplainable error message.
I guess it’s a bug ? I’m filing a bug case right now.
Anybody else having problems with CombineMeshes since 3.4.1f5 ?
Wait, this is an issue completely separate from the one you were experiencing previously… so you’re saying that you are now able to map them correctly? Using a technique similar to the one I posted or something else?
According to the error message, yes it should be completely different. But nothing solved it until I performed this trick, so I guess it’s more a problem of precision from the error message. In a sense, it’s still a problem of number of registered bones against registered bindposes, but it should say that it’s not under the SkinnedMeshRenderer, but under the SharedMesh (sharedMesh.boneIndex0-1-2-3 instead of SkinnedMeshRenderer.bones.Length).
The technique you proposed was not linked to the source of the problem, as it was a problem of serialization under sharedMesh.boneWeights, so I’d say “something else” ^^
In short : before 3.4.1f5, we could just copy sharedMesh.boneWeights to a new BoneWeight[ ] array, and then manipulate that array.
Since 3.4.1f5, we can’t anymore, the array won’t be saved and we have to serialize it before copying it back to sharedMesh.
I guess this is related to recent 3.4 changes about stuff/sharedStuff : now sharedMaterial/sharedMesh/sharedEtc… are really shared, which means they are just references (before you could manipulate them). So now any attempt to change the sharedMesh of an imported FBX (this was the case here) is equivalent to change the FBX’s mesh, which is forbidden. Hence the need to Clone().
I’m not 100% sure of that theory, but that’s my best guess.
oh I see… previously though, didn’t you still have to assign it back to the sharedMesh? I assume you still have to assign it back to the sharedMesh, especially after Clone(), or else it wouldn’t work. I’m assuming these are all structs.
Previous
BoneWeight[] boneWeightsToRemap = SkinnedMeshRenderer.sharedMesh.boneWeights;
// remap all the boneweights
SkinnedMeshRenderer.sharedMesh.boneWeights = boneWeightsToRemap; // <-- I assume you still had to do this?
Current
BoneWeight[] boneWeightsToRemap = (BoneWeights[]) SkinnedMeshRenderer.sharedMesh.boneWeights.Clone() ;
// remap all the boneweights
SkinnedMeshRenderer.sharedMesh.boneWeights = boneWeightsToRemap; // <-- I assume you still have to do this?
I have came up against the sharedMesh problem, it couldn’t been destroyed…
I used the CharacterCustomization example from Unity3D and I have convert into iPhone, it work fine, but numbers of meshes is always increased and increased memory will be crashed. I debug it and find the issue is that SkinnedMeshRenderer.sharedMesh, following is the code: (C#)
public GameObject Generate() {
GameObject root = (GameObject)Object.Instantiate(characterBaseRequests[currentCharacter].asset);
…
SkinnedMeshRenderer r = root.GetComponent();
r.sharedMesh = new Mesh();
r.sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false);
r.bones = bones.ToArray();
r.materials = materials.ToArray();
return root;
}
Another JavaScript call this method, following is the code: (JavaScript)
var assetBundle : GameObject;
assetBundle = generator.Generate();
assetBundle.transform.localScale = Vector3(30, 30, 30);
// Attach the character to this prefab so we can move it around.
assetBundle.transform.parent = transform;
// Play and loop the specified animation.
assetBundle.animation.Play(anim);
assetBundle.animation[anim].wrapMode = WrapMode.Loop;
…
in function FixedUpdate(), I destroy gameObject, as following:
// Destroy the character when it’s out of view.
if (Vector3.Distance(Vector3.zero, transform.position) > 120) {
Destroy(gameObject);
}
The character is really disappeared, but I debug and found the meshes always increased, meshes never be destroyed.
My question is:
If I destroyed a gameObject, the meshed attached should be destroyed also, but it didn’t, why?
Anybody could share how to deal with the sharedMesh?
Thanks lot.
If you created the sharedMesh from scratch (aka. sharedMesh = new Mesh()), yes, you can destroy it at will.
But if you derivate it from an FBX mesh (aka. sharedMesh = FBX.SkinnedMeshRenderer.sharedMesh), you won’t.