Предисловие
В недавнем скриншотнике мы говорили, что работали над оптимизацией. Slash Polygon: Tournament предназначен прежде всего для мобильных платформ, поэтому вопрос производительности для нас почти номер 1.
Mesh Composer
Мы сделали небольшой скрипт, который сшивает меши в один, экономя отрисовку на устройстве. Инструкция использования простая:

- Создайте пустой Game Object
- В качестве Child к созданному объекту добавьте те модели, которые хотите сшить (для них должен использоваться 1 материал, иначе от сшивание нет смысла)
- Добавьте компонент на Game Object - Mesh Composer
- (опционально) Для подчиненных объектов можно включить Mesh Collider

Вcпомогательная информация:
- Total Childs (сколько подчиненных объектов в группе)
- Total Verts (сколько в итоге вертексов получается в сшитом объекте)
- Ругань, если подчиненные сшитые объекты имеют разный материал
- Ругань, если максимальное количество вершин в одном сшитом объекте > 65536
Код
using UnityEngine;
namespace Visual
{
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class MeshComposer : MonoBehaviour
{
public MeshFilter MyFilter;
public MeshRenderer MyRenderer;
public MeshFilter[] InternalFilters;
public Material SharedMaterial;
[SerializeField] private bool _useMeshCollider;
private void Awake()
{
Compose();
}
private void Compose()
{
var combineMeshes = new CombineInstance[InternalFilters.Length];
for (int i = 0; i < combineMeshes.Length; i++)
{
combineMeshes[i].mesh = InternalFilters[i].mesh;
combineMeshes[i].transform = InternalFilters[i].transform.localToWorldMatrix;
InternalFilters[i].gameObject.SetActive(false);
}
MyFilter.mesh = new Mesh();
MyFilter.mesh.CombineMeshes(combineMeshes, true, true, false);
MyRenderer.material = SharedMaterial;
if (_useMeshCollider)
{
var collider = gameObject.AddComponent<MeshCollider>();
collider.sharedMesh = MyFilter.mesh;
}
}
}
}
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Visual.Editor
{
[CustomEditor(typeof(MeshComposer))]
public class MeshComposerInspector : UnityEditor.Editor
{
private MeshComposer _instance;
private void OnEnable()
{
_instance = (MeshComposer) target;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
_instance.MyFilter = _instance.GetComponent<MeshFilter>();
_instance.MyRenderer = _instance.GetComponent<MeshRenderer>();
// fetch childs
_instance.InternalFilters = _instance.GetComponentsInChildren<MeshFilter>()
.Where(filter => filter != _instance.MyFilter).ToArray();
EditorUtility.SetDirty(_instance);
EditorGUILayout.HelpBox($"total childs:{_instance.InternalFilters.Length}", MessageType.Info);
if (_instance.InternalFilters == null || _instance.InternalFilters.Length == 0)
return;
var totalVerts = _instance.InternalFilters.Select(filter => filter.mesh.vertices.Length)
.Aggregate((total, next) => total += next);
var messageType = MessageType.Info;
if (totalVerts > uint.MaxValue)
messageType = MessageType.Error;
EditorGUILayout.HelpBox($"total verts: {totalVerts}", messageType);
var useSameMaterial = true;
var material = _instance.InternalFilters[0].GetComponent<MeshRenderer>().sharedMaterial;
foreach (var meshFilter in _instance.InternalFilters)
{
var rend = meshFilter.GetComponent<MeshRenderer>();
if (rend.sharedMaterial != material)
{
useSameMaterial = false;
break;
}
}
if (!useSameMaterial)
{
EditorGUILayout.HelpBox($"Internal meshses uses different materials, must be the same!",
MessageType.Error);
}
else
{
_instance.SharedMaterial = material;
}
EditorUtility.SetDirty(_instance);
}
}
}
Скачать Mesh Composer
Два готовых скрипта для использования в Unity.
Результат
В видео показан игровой процесс с устройства. В видео стоит ограничитель на максимальный FPS - 30 кадров. Количество Batches и Tris уменшилось на порядок, игра из конкретно нестабильного куска гов билда превратилась в нормальный рабочий прототип.
Смотрите также:
Комментарии
Возможно глупый вопрос, но я пока только вникаю в юнити.
Лоды при этом методе у мешей сохраняются? Какие объекты выгоднее всего таким образом объединять?
Возможно глупый вопрос, но я пока только вникаю в юнити.
Лоды при этом методе у мешей сохраняются? Какие объекты выгоднее всего таким образом объединять?
LOD-ы нет вроде, не делали.
Все существующие меши отключаются на старте, остается только инстансы внутри группировки.
Лучше всего объединять мелкие объекты (мы сшивали лесной участок).


<a href= http://mosros.flybb.ru/viewtopic.php?f=2&t=635>Процесс получения диплома стоматолога: реально ли это сделать быстро?</a>