update
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.ProBuilder;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Unity.FPS.Game
|
||||
{
|
||||
public static class MeshCombineUtility
|
||||
{
|
||||
public class RenderBatchData
|
||||
{
|
||||
public class MeshAndTrs
|
||||
{
|
||||
public Mesh Mesh;
|
||||
public Matrix4x4 Trs;
|
||||
|
||||
public MeshAndTrs(Mesh m, Matrix4x4 t)
|
||||
{
|
||||
Mesh = m;
|
||||
Trs = t;
|
||||
}
|
||||
}
|
||||
|
||||
public Material Material;
|
||||
public int SubmeshIndex = 0;
|
||||
public ShadowCastingMode ShadowMode;
|
||||
public bool ReceiveShadows;
|
||||
public MotionVectorGenerationMode MotionVectors;
|
||||
public List<MeshAndTrs> MeshesWithTrs = new List<MeshAndTrs>();
|
||||
}
|
||||
|
||||
public enum RendererDisposeMethod
|
||||
{
|
||||
DestroyGameObject,
|
||||
DestroyRendererAndFilter,
|
||||
DisableGameObject,
|
||||
DisableRenderer,
|
||||
}
|
||||
|
||||
public static void Combine(List<MeshRenderer> renderers, RendererDisposeMethod disposeMethod,
|
||||
string newObjectName)
|
||||
{
|
||||
int renderersCount = renderers.Count;
|
||||
|
||||
List<RenderBatchData> renderBatches = new List<RenderBatchData>();
|
||||
|
||||
// Build render batches for all unique material + submeshIndex combinations
|
||||
for (int i = 0; i < renderersCount; i++)
|
||||
{
|
||||
MeshRenderer meshRenderer = renderers[i];
|
||||
|
||||
if (meshRenderer == null)
|
||||
continue;
|
||||
|
||||
MeshFilter meshFilter = meshRenderer.GetComponent<MeshFilter>();
|
||||
|
||||
if (meshFilter == null)
|
||||
continue;
|
||||
|
||||
Mesh mesh = meshFilter.sharedMesh;
|
||||
|
||||
if (mesh == null)
|
||||
continue;
|
||||
|
||||
Transform t = meshRenderer.GetComponent<Transform>();
|
||||
Material[] materials = meshRenderer.sharedMaterials;
|
||||
|
||||
for (int s = 0; s < mesh.subMeshCount; s++)
|
||||
{
|
||||
if (materials[s] == null)
|
||||
continue;
|
||||
|
||||
int batchIndex = GetExistingRenderBatch(renderBatches, materials[s], meshRenderer, s);
|
||||
if (batchIndex >= 0)
|
||||
{
|
||||
renderBatches[batchIndex].MeshesWithTrs
|
||||
.Add(new RenderBatchData.MeshAndTrs(mesh,
|
||||
Matrix4x4.TRS(t.position, t.rotation, t.lossyScale)));
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderBatchData newBatchData = new RenderBatchData();
|
||||
newBatchData.Material = materials[s];
|
||||
newBatchData.SubmeshIndex = s;
|
||||
newBatchData.ShadowMode = meshRenderer.shadowCastingMode;
|
||||
newBatchData.ReceiveShadows = meshRenderer.receiveShadows;
|
||||
newBatchData.MeshesWithTrs.Add(new RenderBatchData.MeshAndTrs(mesh,
|
||||
Matrix4x4.TRS(t.position, t.rotation, t.lossyScale)));
|
||||
|
||||
renderBatches.Add(newBatchData);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy probuilder component if present
|
||||
ProBuilderMesh pbm = meshRenderer.GetComponent<ProBuilderMesh>();
|
||||
if (pbm)
|
||||
{
|
||||
GameObject.Destroy(pbm);
|
||||
}
|
||||
|
||||
switch (disposeMethod)
|
||||
{
|
||||
case RendererDisposeMethod.DestroyGameObject:
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
GameObject.Destroy(meshRenderer.gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject.DestroyImmediate(meshRenderer.gameObject);
|
||||
}
|
||||
|
||||
break;
|
||||
case RendererDisposeMethod.DestroyRendererAndFilter:
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
GameObject.Destroy(meshRenderer);
|
||||
GameObject.Destroy(meshFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject.DestroyImmediate(meshRenderer);
|
||||
GameObject.DestroyImmediate(meshFilter);
|
||||
}
|
||||
|
||||
break;
|
||||
case RendererDisposeMethod.DisableGameObject:
|
||||
meshRenderer.gameObject.SetActive(false);
|
||||
break;
|
||||
case RendererDisposeMethod.DisableRenderer:
|
||||
meshRenderer.enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Combine each unique render batch
|
||||
for (int i = 0; i < renderBatches.Count; i++)
|
||||
{
|
||||
RenderBatchData rbd = renderBatches[i];
|
||||
|
||||
Mesh newMesh = new Mesh();
|
||||
newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
|
||||
CombineInstance[] combineInstances = new CombineInstance[rbd.MeshesWithTrs.Count];
|
||||
|
||||
for (int j = 0; j < rbd.MeshesWithTrs.Count; j++)
|
||||
{
|
||||
combineInstances[j].subMeshIndex = rbd.SubmeshIndex;
|
||||
combineInstances[j].mesh = rbd.MeshesWithTrs[j].Mesh;
|
||||
combineInstances[j].transform = rbd.MeshesWithTrs[j].Trs;
|
||||
}
|
||||
|
||||
// Create mesh
|
||||
newMesh.CombineMeshes(combineInstances);
|
||||
newMesh.RecalculateBounds();
|
||||
|
||||
// Create the gameObject
|
||||
GameObject combinedObject = new GameObject(newObjectName);
|
||||
MeshFilter mf = combinedObject.AddComponent<MeshFilter>();
|
||||
mf.sharedMesh = newMesh;
|
||||
MeshRenderer mr = combinedObject.AddComponent<MeshRenderer>();
|
||||
mr.sharedMaterial = rbd.Material;
|
||||
mr.shadowCastingMode = rbd.ShadowMode;
|
||||
}
|
||||
}
|
||||
|
||||
static int GetExistingRenderBatch(List<RenderBatchData> renderBatches, Material mat, MeshRenderer ren, int submeshIndex)
|
||||
{
|
||||
for (int i = 0; i < renderBatches.Count; i++)
|
||||
{
|
||||
RenderBatchData data = renderBatches[i];
|
||||
if (data.Material == mat &&
|
||||
data.SubmeshIndex == submeshIndex &&
|
||||
data.ShadowMode == ren.shadowCastingMode &&
|
||||
data.ReceiveShadows == ren.receiveShadows)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user