From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(C# Code)
(Removing all content from page)
Line 1: Line 1:
Author: Gabriel Santos
== Description ==
Class Model that allows you combine multiple skinned meshes at runtime.
IMPORTANT: The number of vertices and bones is very particular, you must set it up according to your own model.
This Class uses the SkinMeshCombineUtility !
Feel free to clean up the code and add to it. :D
== C# Code ==
@Autor: Gabriel Santos
@Description Class that Combine Multilple SkinnedMeshes in just one Skinned Mesh Renderer
@Usage: Just AddComponent("CombineSkinnedMeshes") to your root component;
@IMPORTANT: This script uses the SkinMeshCombineUtility Script!
PS: It was tested with FBX files exported from 3D MAX
This Vertex Number and Bone Number must be configured according to your own AVATAR...
You can make a Counter to get the Number of Vertices from your imported character, I choice not do it since
this is script is just executed one time... */
using UnityEngine;
using System.Collections;
public class CombineSkinnedMeshes : MonoBehaviour {
/// Usually rendering with triangle strips is faster.
/// However when combining objects with very low triangle counts, it can be faster to use triangles.
/// Best is to try out which value is faster in practice.
public bool castShadows = true;
public bool receiveShadows = true;
/* This is for very particular use, you must set it regarding to your Character */
public static int VERTEX_NUMBER= [Your Vertices Number]; //The number of vertices total of the character
public static int BONE_NUMBER =[Your Bones Number]; //The number of bones total
// Use this for initialization
void Start () {
//Getting all Skinned Renderer from Children
Component[] allsmr = GetComponentsInChildren(typeof(SkinnedMeshRenderer));
Matrix4x4 myTransform = transform.worldToLocalMatrix;
//The hash with the all bones references: it will be used for set up the BoneWeight Indexes
Hashtable boneHash =new Hashtable();
/* If you want make a counter in order to get the total of Vertices and Bones do it here ... */
//The Sum of All Child Bones
Transform[] totalBones = new Transform[BONE_NUMBER];//Total of Bones for my Example
//The Sum of the BindPoses
Matrix4x4[] totalBindPoses = new Matrix4x4[BONE_NUMBER];//Total of BindPoses
//The Sum of BoneWeights
BoneWeight[] totalBoneWeight = new BoneWeight[VERTEX_NUMBER];//total of Vertices for my Example
int offset=0;
int b_offset=0;
Transform[] usedBones= new Transform[totalBones.Length];
ArrayList myInstances = new ArrayList();
//Setting my Arrays for copies
ArrayList myMaterials=new ArrayList();
for(int i=0;i<allsmr.Length;i++)
//Getting one by one
SkinnedMeshRenderer smrenderer  =  (SkinnedMeshRenderer)allsmr[i];
//Making changes to the Skinned Renderer
SkinMeshCombineUtility.MeshInstance instance = new SkinMeshCombineUtility.MeshInstance ();
//Setting the Mesh for the instance
instance.mesh = smrenderer.sharedMesh;
//Getting All Materials
for(int t=0;t<smrenderer.sharedMaterials.Length;t++)
if (smrenderer != null && smrenderer.enabled && instance.mesh != null) {
instance.transform = myTransform * smrenderer.transform.localToWorldMatrix;
//Material == null
smrenderer.sharedMaterials =new  Material[1];
//Getting  subMesh
for(int t=0;t<smrenderer.sharedMesh.subMeshCount;t++)
instance.subMeshIndex = t;
//Copying Bones
for(int x=0;x<smrenderer.bones.Length;x++)
bool flag = false;
for(int j=0;j<totalBones.Length;j++)
//If the bone was already inserted
flag = true;
//If Bone is New ...
//Debug.Log("Inserted bone:"+smrenderer.bones[x].name);
for(int f=0;f<totalBones.Length;f++)
//Insert bone at the firs free position
usedBones[f] = smrenderer.bones[x];
//inserting bones in totalBones
//Reference HashTable
//Recalculating BindPoses
//totalBindPoses[offset] = smrenderer.sharedMesh.bindposes[x] ;
totalBindPoses[offset] = smrenderer.bones[x].worldToLocalMatrix * transform.localToWorldMatrix ;
for(int x=0;x<smrenderer.sharedMesh.boneWeights.Length ;x++)
//Just Copying and changing the Bones Indexes !!
totalBoneWeight[b_offset] =  recalculateIndexes(smrenderer.sharedMesh.boneWeights[x],boneHash,smrenderer.bones);
//Disabling current SkinnedMeshRenderer
((SkinnedMeshRenderer)allsmr[i]).enabled = false;
SkinMeshCombineUtility.MeshInstance[] instances = (SkinMeshCombineUtility.MeshInstance[])myInstances.ToArray(typeof(SkinMeshCombineUtility.MeshInstance));
// Make sure we have a SkinnedMeshRenderer
if (GetComponent(typeof(SkinnedMeshRenderer)) == null)
//Setting Skinned Renderer
SkinnedMeshRenderer objRenderer = (SkinnedMeshRenderer)GetComponent(typeof(SkinnedMeshRenderer));
//Setting Mesh
objRenderer.sharedMesh = SkinMeshCombineUtility.Combine(instances);
objRenderer.castShadows = castShadows;
objRenderer.receiveShadows = receiveShadows;
//Setting Bindposes
objRenderer.sharedMesh.bindposes = totalBindPoses;
//Setting BoneWeights
objRenderer.sharedMesh.boneWeights = totalBoneWeight;
//Setting bones
objRenderer.bones =totalBones;
//Setting Materials
objRenderer.sharedMaterials = (Material[])myMaterials.ToArray(typeof(Material));
//Enable Mesh
objRenderer.enabled = true;
/* Debug.Log("############################################");
Debug.Log("M Materials "+myMaterials.Count);
Debug.Log("bindPoses "+objRenderer.sharedMesh.bindposes.Length);
Debug.Log("boneWeights "+objRenderer.sharedMesh.boneWeights.Length);
Debug.Log("Bones "+objRenderer.bones.Length);
Debug.Log("Vertices "+objRenderer.sharedMesh.vertices.Length); */
@Description: Revert the order of an array of components
static Component[] revertComponent(Component[] comp )
Component[] result = new Component[comp.Length];
int x=0;
for(int i=comp.Length-1;i>=0;i--)
return result;
@Description: Setting the Indexes for the new bones
static BoneWeight recalculateIndexes(BoneWeight bw,Hashtable boneHash,Transform[] meshBones )
BoneWeight retBw = bw;
retBw.boneIndex0 = (int)boneHash[meshBones[bw.boneIndex0].name];
retBw.boneIndex1 = (int)boneHash[meshBones[bw.boneIndex1].name];
retBw.boneIndex2 = (int)boneHash[meshBones[bw.boneIndex2].name];
retBw.boneIndex3 = (int)boneHash[meshBones[bw.boneIndex3].name];
return retBw;

Revision as of 18:14, 19 October 2009

Personal tools