Combine Children Extented (расширенный)

Оптимизация моделей, текстур, звуков

Combine Children Extented (расширенный)

Сообщение Neodrop 25 дек 2009, 18:45

Как известно, объединение объектов, использующих один материал в группу, сильно повышает производительность. Для этого в стандартной поставке Unity существует скрипт Combine Children (далее : Комбайн)
В процессе работы, накопились некоторые добавки к стандартному скрипту Комбайна. Делюсь :

Изображение

[V] Frame To Wait : сколько кадров на старте скрипта, ждать, прежде чем произвести объединение.
К примеру, у вас есть объект, содержащий ещё сотню объектов, которые в свою очередь содержат чилдов. Префаб внутренних объектов, оборудован Комбайном с собственными настройками. На старте, все они скомбайнятся и мы получим поменьше мешей, но всё равно кучу. Почему бы не скомбайнить их снова?
Ставим циферку 1 и в следующем кадре, после завершения комбайнинга чилдов, слепляем полученные меши вновь и получаем 5 - 10 мешей вместо старых сотен.
[V] Combine On Start - скрипт сработает на старте композиции (если он активирован, конечно).
[V] Destroy After Optimized - убить все исходные объекты. Осторожно! Если на этих объектах коллайдеры, они тоже будут уничтожены.
[V] Cast Shadow - конечная меш будет отбрасывать тени.
[V] Receive Shadow - конечная меш будет принимать тени.
[V] Keep Layer - созданный объект сохранит тот же слой, что и у исходного объекта (на котором висит скрипт)

Ну и, замечательный бонус! :ymparty:
[V] Под правой кнопкой живёт команда Combine Now. Она позволяет провести всё комбинирование прямо в Редакторе, оценить изминения и, или отменить их (созданные меши нужно будет удалить руками) или сохранить. То есть - избежать необходимости комбайнить на старте приложения.

Изображение

Мне он очень сильно помог и помогает в оптимизации сцен. Надеюсь и вам пригодиться.
З.Ы. Для его работы нужен стандартный скрипт MeshCombineUtility.cs из Standart Assets
У вас нет доступа для просмотра вложений в этом сообщении.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8449
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Combine Children Extented (расширенный)

Сообщение Serge 25 дек 2009, 19:12

Спасибо. (3A4OT)
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

Re: Combine Children Extented (расширенный)

Сообщение iqubik 25 дек 2009, 19:32

Neo спасибо за проделанную работу!
Я думаю скрипт будет действительно ценен. По крайней мере для себя я уже вижу очевидные выгоды его применения.
Но вот всё таки у меня остался один важный вопрос.
Если я зохочу приатачить 2 объекта с разными матами, то видимо скрипт мне объяснит как я не прав.
Но чисто теоретически, можно ли сделать так, чтобы комбайнер при атаче разнородных материалов раздавал бы новообразовавшемуся объекту айдишники и присваивал мультимат?
И опять же, чисто теоретически - насколько трудоёмко дописать такой модуль?
----------------------
qub edition
Идеальное общество это общество где каждый станет настолько эгоистом, что начнёт понимать, что делая недоброе другому получит тоже в ответ. (око за око, с прощением)
iqubik
UNIт
 
Сообщения: 74
Зарегистрирован: 11 июн 2009, 13:38
Откуда: Stavropol
  • Сайт
  • ICQ

Re: Combine Children Extented (расширенный)

Сообщение Neodrop 25 дек 2009, 19:44

На каждый мат создаётся свой меш.
Мультиматы страшное зло для [unity 3D] Unity и для оптимизации программы. Вот для таких экспериментов я и добавил возможность комбайнить в Редакторе. Эксперементируйте.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8449
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Combine Children Extented (расширенный)

Сообщение Neodrop 27 дек 2009, 16:22

Ещё маленько расширил функционал, добавив возможность вызвать комбайн на всех чилдах, исключая объект, с которого команда вызвана.

Качаем тут :

http://forum.unity3d.com/viewtopic.php?p=247996#247996

[ftp]http://forum.unity3d.com/viewtopic.php?p=247996#247996[/ftp]
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8449
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Combine Children Extented (расширенный)

Сообщение iqubik 07 янв 2010, 21:27

Спасибо Нео за компайнер!
И спасибо romeo_ftv за доработку комбайнера под юнити 2.6 (там всего одна строка, но без неё на 2.6 не работает).
Вот тот же комбайнер, но для 2.6.


Код: Выделить всё
using UnityEngine;
using System.Collections;


/*
Attach this script as a parent to some game objects. The script will then combine the meshes at startup.
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.

Different materials will cause multiple meshes to be created, thus it is useful to share as many textures/material as you can.
*/
//[ExecuteInEditMode()]
[AddComponentMenu("Mesh/Combine Children")]
public class CombineChildren : 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 int frameToWait = 0;
   public bool generateTriangleStrips = true, combineOnStart = true, destroyAfterOptimized = false, castShadow = true, receiveShadow = true, keepLayer = true;
   
    void Start()
    {
        if (combineOnStart && frameToWait == 0) Combine();
        else StartCoroutine(CombineLate());
    }

    IEnumerator CombineLate()
    {
        for (int i = 0; i < frameToWait; i++ ) yield return 0;
        Combine();
    }

    [ContextMenu("Combine Now on Childs")]
    public void CallCombineOnAllChilds()
    {
        //CombineChildren[] c = gameObject.GetComponentsInChildren<CombineChildren>();
      CombineChildren[] c = (CombineChildren[])GetComponentsInChildren( typeof(CombineChildren) );
        int count = c.Length;
        for (int i = 0; i < count; i++) if(c[i] != this)c[i].Combine();
        combineOnStart = enabled = false;
    }

   /// This option has a far longer preprocessing time at startup but leads to better runtime performance.
    [ContextMenu ("Combine Now")]
   public void Combine () {
      Component[] filters  = GetComponentsInChildren(typeof(MeshFilter));
      Matrix4x4 myTransform = transform.worldToLocalMatrix;
      Hashtable materialToMesh= new Hashtable();
      
      for (int i=0;i<filters.Length;i++) {
         MeshFilter filter = (MeshFilter)filters[i];
         Renderer curRenderer  = filters[i].renderer;
         MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance ();
         instance.mesh = filter.sharedMesh;
         if (curRenderer != null && curRenderer.enabled && instance.mesh != null) {
            instance.transform = myTransform * filter.transform.localToWorldMatrix;
            
            Material[] materials = curRenderer.sharedMaterials;
            for (int m=0;m<materials.Length;m++) {
               instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1);
   
               ArrayList objects = (ArrayList)materialToMesh[materials[m]];
               if (objects != null) {
                  objects.Add(instance);
               }
               else
               {
                  objects = new ArrayList ();
                  objects.Add(instance);
                  materialToMesh.Add(materials[m], objects);
               }
            }
                if (Application.isPlaying && destroyAfterOptimized && combineOnStart) Destroy(curRenderer.gameObject);
                else if (destroyAfterOptimized) DestroyImmediate(curRenderer.gameObject);
            else curRenderer.enabled = false;
         }
      }
   
      foreach (DictionaryEntry de  in materialToMesh) {
         ArrayList elements = (ArrayList)de.Value;
         MeshCombineUtility.MeshInstance[] instances = (MeshCombineUtility.MeshInstance[])elements.ToArray(typeof(MeshCombineUtility.MeshInstance));

         // We have a maximum of one material, so just attach the mesh to our own game object
         if (materialToMesh.Count == 1)
         {
            // Make sure we have a mesh filter & renderer
            if (GetComponent(typeof(MeshFilter)) == null)
               gameObject.AddComponent(typeof(MeshFilter));
            if (!GetComponent("MeshRenderer"))
               gameObject.AddComponent("MeshRenderer");
   
            MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter));
            filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips);
            renderer.material = (Material)de.Key;
            renderer.enabled = true;
         }
         // We have multiple materials to take care of, build one mesh / gameobject for each material
         // and parent it to this object
         else
         {
            GameObject go = new GameObject("Combined mesh");
                if (keepLayer) go.layer = gameObject.layer;
            go.transform.parent = transform;
            go.transform.localScale = Vector3.one;
            go.transform.localRotation = Quaternion.identity;
            go.transform.localPosition = Vector3.zero;
            go.AddComponent(typeof(MeshFilter));
            go.AddComponent("MeshRenderer");
            go.renderer.material = (Material)de.Key;
            MeshFilter filter = (MeshFilter)go.GetComponent(typeof(MeshFilter));
            if(Application.isPlaying)filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips);
                else filter.sharedMesh = MeshCombineUtility.Combine(instances, generateTriangleStrips);
                go.renderer.castShadows = castShadow;
                go.renderer.receiveShadows = receiveShadow;
         }
      }   
   }   
}
----------------------
qub edition
Идеальное общество это общество где каждый станет настолько эгоистом, что начнёт понимать, что делая недоброе другому получит тоже в ответ. (око за око, с прощением)
iqubik
UNIт
 
Сообщения: 74
Зарегистрирован: 11 июн 2009, 13:38
Откуда: Stavropol
  • Сайт
  • ICQ

Re: Combine Children Extented (расширенный)

Сообщение Neodrop 08 янв 2010, 11:32

Я работаю на 2.6.1 Как это у вас не работает? :-?
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8449
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Combine Children Extented (расширенный)

Сообщение iqubik 08 янв 2010, 18:17

Сорри, для 2.5.
И кстати эта правка не помогла. Вместо пункта меня "Combine childrens now" вижу чтото вроде "АПпапапап@43"...
А это как выходит блок памяти откуда-то преобразованный в стринговое значение.
----------------------
qub edition
Идеальное общество это общество где каждый станет настолько эгоистом, что начнёт понимать, что делая недоброе другому получит тоже в ответ. (око за око, с прощением)
iqubik
UNIт
 
Сообщения: 74
Зарегистрирован: 11 июн 2009, 13:38
Откуда: Stavropol
  • Сайт
  • ICQ

Re: Combine Children Extented (расширенный)

Сообщение Neodrop 08 янв 2010, 20:45

Это в 2.5 что ли? НА него я не ориентировался. Может там нет чего-то, использованного в коде.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8449
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Combine Children Extented (расширенный)

Сообщение iqubik 09 янв 2010, 02:01

Да, синтаксис 2,5 не позволил.
Но в любом случае, Нео, спасибо тебе за то что ты реализовал функции attach-а(по требованию) + задержка комбайна + слои!!!!
Огромное человеческое СПАСИБО!
А вторичная функция на то и вторичная - маст дизаблед))
----------------------
qub edition
Идеальное общество это общество где каждый станет настолько эгоистом, что начнёт понимать, что делая недоброе другому получит тоже в ответ. (око за око, с прощением)
iqubik
UNIт
 
Сообщения: 74
Зарегистрирован: 11 июн 2009, 13:38
Откуда: Stavropol
  • Сайт
  • ICQ

Re: Combine Children Extented (расширенный)

Сообщение Neodrop 01 фев 2010, 18:08

Малость подправил - не работало в Редакторе, когда материал только один. Перезалито на офф. форум (смотрим ссылку чуть выше.)
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8449
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Combine Children Extented (расширенный)

Сообщение jytu 22 авг 2010, 19:27

Пасиб, Неодроп )

эта штука сэкономила кучу времени :)
jytu
UNец
 
Сообщения: 37
Зарегистрирован: 31 окт 2009, 18:36

Re: Combine Children Extented (расширенный)

Сообщение strelok 10 окт 2010, 18:27

При добавлении скрипта (CombineChildren), все объекты, находящиеся в группе исчезают во время запуска. Что за хрень? Как бороться?
strelok
UNIверсал
 
Сообщения: 356
Зарегистрирован: 15 ноя 2009, 13:29
Откуда: Курск

Re: Combine Children Extented (расширенный)

Сообщение Neodrop 10 окт 2010, 18:29

Не все модели комбайнятся нормально. Видимо модели у вас кривоваты. Обычно помогает ResetX Form в Максе перед экспортом в двиг. Конечно, если вы работаете в Максе.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8449
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Combine Children Extented (расширенный)

Сообщение strelok 10 окт 2010, 18:56

Век живи - век учись! Изначально объекты были в формате .obj, теперь в .fbx и всё нормуль. Спасибо!
strelok
UNIверсал
 
Сообщения: 356
Зарегистрирован: 15 ноя 2009, 13:29
Откуда: Курск

След.

Вернуться в Медиа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1