블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2794)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (234)
협업 (11)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

링크 : http://forum.unity3d.com/threads/159693-GenerateSecondaryUVSet-destroying-mesh



Answering to my own thread here.

It seems like the MeshMerger script from the wiki itself was causing this trouble. On fourth thought and investigation it seems like copying of triangles and vertices is kind of buggy in the script, so finally I also saw some lonesome vertices flowing in the world after combining. Therefore it might not be the best idea to use that script at all.

Nevertheless, the CombineChildren script from the Standard Assets turned out to be a much better basis to work with. I've rewritten parts of it now to suit my needs, which basically is generating the combined static geometry in the editor and being able to generate lightmaps for this as well. Works like a charm!

I've seen this topic multiple times in the community without a real solution, so it might be a good idea to have a script ready for this. No big adjustment, but I hope it helps some people out there. Here it is, use it as you wish.

CombineChildrenAdvanced.cs
Usage: Place this anywhere in your project and attach it to the parent gameObject containing the other meshes to be combined.
Basically it delivers the very same feature as the standard CombineChildren script, yet it needs to be executed in the editor.
By default it'll automatically generate the lightmapping UVs for the combined geometry. If you don't want this to happen, either use the CombineChildren.cs from the Standard Assets, or uncheck the corresponding checkbox.
If you want to split geometry up again, just use the corresponding button. It'll reset everything accordingly.

Code:  
  1. using UnityEngine;
  2. using System.Collections;
  3. /*
  4. Attach this script as a parent to some game objects. Then by using the corresponding controls you may generate combined meshes (with lightmapping UVs).
  5. This is useful as a performance optimization since it is faster to render one big mesh than many small meshes. See the docs on graphics performance optimization for more info.
  6.  
  7. Different materials will cause multiple meshes to be created, thus it is useful to share as many textures/material as you can.
  8. NOTE: Using multiple materials may break things due to lightmapping generation. So lightmapping UVs as well as splitting the combined geometry is not supported.
  9. Workaround: Create hierarchies in which the children only have exactly one material.
  10. */
  11.  
  12. [AddComponentMenu("Mad Vulture Games/Combine Children 1.5")]
  13. public class CombineChildrenAdvanced : MonoBehaviour {
  14.    
  15.     /// Usually rendering with triangle strips is faster.
  16.     /// However when combining objects with very low triangle counts, it can be faster to use triangles.
  17.     /// Best is to try out which value is faster in practice.
  18.     public bool generateTriangleStrips = true;
  19.     public bool generateLightmappingUVs = true;
  20.     public bool isCombined = false;
  21.    
  22.     public void Combine() {
  23.         Component[] filters  = GetComponentsInChildren(typeof(MeshFilter));
  24.        
  25.         if (filters.Length <= 1) {
  26.             Debug.LogWarning ("Not enough meshes to combine!");
  27.             return;
  28.         }
  29.        
  30.         Matrix4x4 myTransform = transform.worldToLocalMatrix;
  31.         Hashtable materialToMesh= new Hashtable();
  32.        
  33.         for (int i=0;i<filters.Length;i++) {
  34.             MeshFilter filter = (MeshFilter)filters[i];
  35.             Renderer curRenderer  = filters[i].renderer;
  36.             MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance ();
  37.             instance.mesh = filter.sharedMesh;
  38.             if (curRenderer != null && curRenderer.enabled && instance.mesh != null) {
  39.                 instance.transform = myTransform * filter.transform.localToWorldMatrix;
  40.                
  41.                 Material[] materials = curRenderer.sharedMaterials;
  42.                 for (int m=0;m<materials.Length;m++) {
  43.                     instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1);
  44.    
  45.                     ArrayList objects = (ArrayList)materialToMesh[materials[m]];
  46.                     if (objects != null) {
  47.                         objects.Add(instance);
  48.                     }
  49.                     else
  50.                     {
  51.                         objects = new ArrayList ();
  52.                         objects.Add(instance);
  53.                         materialToMesh.Add(materials[m], objects);
  54.                     }
  55.                 }
  56.                
  57.                 curRenderer.enabled = false;
  58.             }
  59.         }
  60.    
  61.         foreach (DictionaryEntry de  in materialToMesh) {
  62.             ArrayList elements = (ArrayList)de.Value;
  63.             MeshCombineUtility.MeshInstance[] instances = (MeshCombineUtility.MeshInstance[])elements.ToArray(typeof(MeshCombineUtility.MeshInstance));
  64.  
  65.             // We have a maximum of one material, so just attach the mesh to our own game object
  66.             if (materialToMesh.Count == 1)
  67.             {
  68.                 // Make sure we have a mesh filter & renderer
  69.                 if (GetComponent(typeof(MeshFilter)) == null)
  70.                     gameObject.AddComponent(typeof(MeshFilter));
  71.                 if (!GetComponent("MeshRenderer"))
  72.                     gameObject.AddComponent("MeshRenderer");
  73.    
  74.                 MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter));
  75.                 filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips);
  76.                 renderer.material = (Material)de.Key;
  77.                 renderer.enabled = true;
  78.             }
  79.             // We have multiple materials to take care of, build one mesh / gameobject for each material
  80.             // and parent it to this object
  81.             else
  82.             {
  83.                 GameObject go = new GameObject("Combined mesh");
  84.                 go.transform.parent = transform;
  85.                 go.transform.localScale = Vector3.one;
  86.                 go.transform.localRotation = Quaternion.identity;
  87.                 go.transform.localPosition = Vector3.zero;
  88.                 go.AddComponent(typeof(MeshFilter));
  89.                 go.AddComponent("MeshRenderer");
  90.                 go.renderer.material = (Material)de.Key;
  91.                 MeshFilter filter = (MeshFilter)go.GetComponent(typeof(MeshFilter));
  92.                 filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips);
  93.             }
  94.         }
  95.        
  96.         isCombined = true;
  97.     }
  98. }






CombineChildrenAdvancedEditor.cs
Usage: Place this in your Assets/Editor folder, it actually contains the main part of it.

Code:  
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections;
  4.  
  5. [CustomEditor(typeof(CombineChildrenAdvanced))]
  6. public class CombineChildrenAdvancedEditor : Editor {
  7.  
  8.     CombineChildrenAdvanced _target;
  9.    
  10.     void OnEnable() {
  11.         _target = (CombineChildrenAdvanced)target;
  12.     }
  13.    
  14.    
  15.    
  16.     public override void OnInspectorGUI() {
  17.        
  18.        
  19.         _target.generateTriangleStrips = EditorGUILayout.Toggle("Generate Triangle Strips", _target.generateTriangleStrips);
  20.         _target.generateLightmappingUVs = EditorGUILayout.Toggle ("Generate Lightmapping UVs", _target.generateLightmappingUVs);
  21.        
  22.         if (!_target.isCombined) {
  23.             if (GUILayout.Button ("Combine now (May take a while!)")) {
  24.                 _target.Combine();
  25.                
  26.                 if (_target.generateLightmappingUVs) {
  27.                     GenerateLightmappingUVs();
  28.                 }
  29.             }
  30.         }
  31.        
  32.         if (_target.isCombined) {
  33.             if (GUILayout.Button ("Generate Lightmap UVs")) {
  34.                 GenerateLightmappingUVs();
  35.             }
  36.            
  37.             if (GUILayout.Button ("Split Mesh")) {
  38.                 DestroyImmediate(_target.GetComponent (typeof(MeshFilter)));
  39.                 DestroyImmediate(_target.GetComponent (typeof(MeshRenderer)));
  40.                
  41.                 foreach (MeshRenderer mr in _target.GetComponentsInChildren(typeof(MeshRenderer))) {
  42.                     mr.enabled = true;
  43.                 }
  44.                
  45.                 _target.isCombined = false;
  46.             }
  47.         }
  48.     }
  49.    
  50.    
  51.    
  52.    
  53.     void GenerateLightmappingUVs() {
  54.         MeshFilter mf = _target.GetComponent(typeof(MeshFilter)) as MeshFilter;
  55.        
  56.         // make null check because if not enough meshes are present no combined mesh would have been created!
  57.         if (mf != null) {
  58.         }
  59.     }
  60.    
  61. }

Note: While the script still gives you the opportunity to use it with meshes with multiple materials (which will effectively generate multiple new gameObjects), this is not supported in this version, you might get errors. If you need that, feel free to build that yourself or let me know, shouldn't be hard to add.

반응형
Posted by blueasa
, |