From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
m (Text replace - "<javascript>" to "<syntaxhighlight lang="javascript">")
m (Text replace - "</javascript>" to "</syntaxhighlight>")
Line 160: Line 160:

Latest revision as of 20:52, 10 January 2012

// Mesh Merger Script
// Copyright 2009, Russ Menapace
// Summary:
//  This script allows you to draw a large number of meshes with a single 
//  draw call.  This is particularly useful for iPhone games.
// License:
//  Free to use as you see fit, but I would appreciate one of the following:
//  * A credit for Human Powered Games, or even a link to
//    in whatever you make with this
//  * Hire me to make games or simulations
//  * A donation to the PayPal account at  I'm very poor, so 
//    even a small donation would be greatly appreciated!
//  * A thank you note to
//  * Suggestions on how the script could be improved mailed to
// Warranty:
//  This software carries no warranty, and I don't guarantee anything about it.
//  If it burns down your house or gets your cat pregnant, don't look at me. 
// Acnowledgements: 
//  This was pieced together out of code I found onthe UnifyCommunity wiki, and 
//  the Unity forum.  I did not keep track of names, but I do recall gaining
//  a lot of insight from the posts of PirateNinjaAlliance.  
//  Thanks to anybody that may have been involved.
// Requirements:  
//  All the meshes you want to use must use the same material.  
//  This material may be a texture atlas and the meshes UV to portions of the atlas.
//  The texture atlas technique works particularly well for GUI stuff.
// Usage:
//  There are two ways to use this script:
//  Implicit:  
//    Simply drop the script into a GameObject that has a number of
//    child objects containing mesh filters.
//  Explicit:
//    Populate the meshFilter array with the meshes you want merged
//    Optionally, set the material to be used.  If no material is selected,
//    The script will apply the first material it encounters to all subsequent
//    meshes
// To see if it's working:
//  Move the camera so you can see several of your objects in the Game pane
//  Note the number of draw calls
//  Hit play. You should see the number of draw calls for those meshes reduced to one
using UnityEngine;
using System;
public class MeshMerger : MonoBehaviour 
  public MeshFilter[] meshFilters;
  public Material material;
  void Start () 
    // if not specified, go find meshes
    if(meshFilters.Length == 0)
      // find all the mesh filters
      Component[] comps = GetComponentsInChildren(typeof(MeshFilter));
      meshFilters = new MeshFilter[comps.Length];
      int mfi = 0;
      foreach(Component comp in comps)
        meshFilters[mfi++] = (MeshFilter) comp;
    // figure out array sizes
    int vertCount = 0;
    int normCount = 0;
    int triCount = 0;
    int uvCount = 0;
    foreach(MeshFilter mf in meshFilters)
      vertCount += mf.mesh.vertices.Length; 
      normCount += mf.mesh.normals.Length;
      triCount += mf.mesh.triangles.Length; 
      uvCount += mf.mesh.uv.Length;
      if(material == null)
        material = mf.gameObject.renderer.material;       
    // allocate arrays
    Vector3[] verts = new Vector3[vertCount];
    Vector3[] norms = new Vector3[normCount];
    Transform[] aBones = new Transform[meshFilters.Length];
    Matrix4x4[] bindPoses = new Matrix4x4[meshFilters.Length];
    BoneWeight[] weights = new BoneWeight[vertCount];
    int[] tris  = new int[triCount];
    Vector2[] uvs = new Vector2[uvCount];
    int vertOffset = 0;
    int normOffset = 0;
    int triOffset = 0;
    int uvOffset = 0;
    int meshOffset = 0;
    // merge the meshes and set up bones
    foreach(MeshFilter mf in meshFilters)
      foreach(int i in mf.mesh.triangles)
        tris[triOffset++] = i + vertOffset;
      aBones[meshOffset] = mf.transform;
      bindPoses[meshOffset] = Matrix4x4.identity;
      foreach(Vector3 v in mf.mesh.vertices)
        weights[vertOffset].weight0 = 1.0f;
        weights[vertOffset].boneIndex0 = meshOffset;
        verts[vertOffset++] = v;
      foreach(Vector3 n in mf.mesh.normals)
        norms[normOffset++] = n;
      foreach(Vector2 uv in mf.mesh.uv)
        uvs[uvOffset++] = uv;
      MeshRenderer mr = 
        as MeshRenderer;
        mr.enabled = false;
    // hook up the mesh
    Mesh me = new Mesh();   =;
    me.vertices = verts;
    me.normals = norms;
    me.boneWeights = weights;
    me.uv = uvs;
    me.triangles = tris;
    me.bindposes = bindPoses;
    // hook up the mesh renderer        
    SkinnedMeshRenderer smr = 
      as SkinnedMeshRenderer;
    smr.sharedMesh = me;
    smr.bones = aBones;
    renderer.material = material;
Personal tools