static void GenerateLODs(GameObject go) { // A NOP to make sure we have an instance before launching into threads that may need to execute on the main thread MonoBehaviourHelper.ExecuteOnMainThread(() => {}); var meshFilters = go.GetComponentsInChildren <MeshFilter>(); if (meshFilters.Length > 0) { var lodGroup = go.GetComponent <LODGroup>(); if (!lodGroup) { lodGroup = go.AddComponent <LODGroup>(); } var lods = new LOD[maxLOD + 1]; var lod0 = lods[0]; lod0.renderers = go.GetComponentsInChildren <MeshRenderer>(); lod0.screenRelativeTransitionHeight = 0.5f; lods[0] = lod0; var meshes = new List <Mesh>(); for (int l = 1; l <= maxLOD; l++) { var lodRenderers = new List <MeshRenderer>(); foreach (var mf in meshFilters) { var sharedMesh = mf.sharedMesh; if (!sharedMesh) { Debug.LogWarning("AutoLOD: Missing mesh " + mf.name, mf); continue; } var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l), k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform; lodTransform.SetParent(mf.transform, false); var lodMF = lodTransform.GetComponent <MeshFilter>(); var lodRenderer = lodTransform.GetComponent <MeshRenderer>(); lodRenderers.Add(lodRenderer); EditorUtility.CopySerialized(mf, lodMF); EditorUtility.CopySerialized(mf.GetComponent <MeshRenderer>(), lodRenderer); var simplifiedMesh = new Mesh(); simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l); lodMF.sharedMesh = simplifiedMesh; meshes.Add(simplifiedMesh); var meshLOD = MeshLOD.GetGenericInstance(meshSimplifierType); meshLOD.InputMesh = sharedMesh; meshLOD.OutputMesh = simplifiedMesh; meshLOD.Quality = Mathf.Pow(0.5f, l); meshLOD.Generate(); } var lod = lods[l]; lod.renderers = lodRenderers.ToArray(); lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(0.5f, l + 1); lods[l] = lod; } lodGroup.ForceLOD(0); lodGroup.SetLODs(lods.ToArray()); lodGroup.RecalculateBounds(); lodGroup.ForceLOD(-1); #if UNITY_2018_2_OR_NEWER var prefab = PrefabUtility.GetCorrespondingObjectFromSource(go); #else var prefab = PrefabUtility.GetPrefabParent(go); #endif if (prefab) { var lodsAssetPath = GetLODAssetPath(prefab); if (File.Exists(lodsAssetPath)) { meshes.ForEach(m => AssetDatabase.AddObjectToAsset(m, lodsAssetPath)); } else { ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath); } } } }
void GenerateLODs(Action completedCallback) { int maxLOD = 1; var go = gameObject; var hlodLayer = LayerMask.NameToLayer(HLODLayer); var lodGroup = go.GetComponent <LODGroup>(); if (lodGroup) { var lods = new LOD[maxLOD + 1]; var lod0 = lodGroup.GetLODs()[0]; lod0.screenRelativeTransitionHeight = 0.5f; lods[0] = lod0; var meshes = new List <Mesh>(); var totalMeshCount = maxLOD * lod0.renderers.Length; var runningMeshCount = 0; for (int l = 1; l <= maxLOD; l++) { var lodRenderers = new List <MeshRenderer>(); foreach (var mr in lod0.renderers) { var mf = mr.GetComponent <MeshFilter>(); var sharedMesh = mf.sharedMesh; var lodTransform = UnityEditor.EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l), k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform; lodTransform.gameObject.layer = hlodLayer; lodTransform.SetPositionAndRotation(mf.transform.position, mf.transform.rotation); lodTransform.localScale = mf.transform.lossyScale; lodTransform.SetParent(mf.transform, true); var lodMF = lodTransform.GetComponent <MeshFilter>(); var lodRenderer = lodTransform.GetComponent <MeshRenderer>(); lodRenderers.Add(lodRenderer); UnityEditor.EditorUtility.CopySerialized(mf, lodMF); UnityEditor.EditorUtility.CopySerialized(mf.GetComponent <MeshRenderer>(), lodRenderer); var simplifiedMesh = new Mesh(); simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l); lodMF.sharedMesh = simplifiedMesh; meshes.Add(simplifiedMesh); var index = l; var inputMesh = sharedMesh.ToWorkingMesh(); var outputMesh = simplifiedMesh.ToWorkingMesh(); var meshSimplifier = (IMeshSimplifier)Activator.CreateInstance(meshSimplifierType); meshSimplifier.Simplify(inputMesh, outputMesh, Mathf.Pow(meshSimplificationRatio, l), () => { Debug.Log("Completed LOD " + index); outputMesh.ApplyToMesh(simplifiedMesh); simplifiedMesh.RecalculateBounds(); runningMeshCount++; Debug.Log(runningMeshCount + " vs " + totalMeshCount); if (runningMeshCount == totalMeshCount && completedCallback != null) { completedCallback(); } }); } var lod = lods[l]; lod.renderers = lodRenderers.ToArray(); lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(meshSimplificationRatio, l + 1); lods[l] = lod; } lodGroup.ForceLOD(0); lodGroup.SetLODs(lods.ToArray()); lodGroup.RecalculateBounds(); lodGroup.ForceLOD(-1); #if UNITY_2018_2_OR_NEWER var prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(go); #else var prefab = UnityEditor.PrefabUtility.GetPrefabParent(go); #endif if (prefab) { var assetPath = UnityEditor.AssetDatabase.GetAssetPath(prefab); var pathPrefix = Path.GetDirectoryName(assetPath) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(assetPath); var lodsAssetPath = pathPrefix + "_lods.asset"; ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath); } } }
static void GenerateLODs(GameObject go) { // A NOP to make sure we have an instance before launching into threads that may need to execute on the main thread MonoBehaviourHelper.ExecuteOnMainThread(() => {}); var meshFilters = go.GetComponentsInChildren <MeshFilter>(); if (meshFilters.Length > 0) { var lodGroup = go.GetComponent <LODGroup>(); if (!lodGroup) { lodGroup = go.AddComponent <LODGroup>(); } var lods = new LOD[maxLOD + 1]; var lod0 = lods[0]; lod0.renderers = go.GetComponentsInChildren <MeshRenderer>(); lod0.screenRelativeTransitionHeight = 0.5f; lods[0] = lod0; var meshes = new List <Mesh>(); for (int l = 1; l <= maxLOD; l++) { var lodRenderers = new List <MeshRenderer>(); foreach (var mf in meshFilters) { var sharedMesh = mf.sharedMesh; if (!sharedMesh) { Debug.LogWarning("AutoLOD: Missing mesh " + mf.name, mf); continue; } var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l), k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform; lodTransform.SetParent(mf.transform, false); var lodMF = lodTransform.GetComponent <MeshFilter>(); var lodRenderer = lodTransform.GetComponent <MeshRenderer>(); lodRenderers.Add(lodRenderer); EditorUtility.CopySerialized(mf, lodMF); EditorUtility.CopySerialized(mf.GetComponent <MeshRenderer>(), lodRenderer); var simplifiedMesh = new Mesh(); simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l); lodMF.sharedMesh = simplifiedMesh; meshes.Add(simplifiedMesh); var worker = new BackgroundWorker(); var index = l; var inputMesh = sharedMesh.ToWorkingMesh(); var outputMesh = simplifiedMesh.ToWorkingMesh(); var meshSimplifier = (IMeshSimplifier)Activator.CreateInstance(meshSimplifierType); worker.DoWork += (sender, args) => { meshSimplifier.Simplify(inputMesh, outputMesh, Mathf.Pow(0.5f, index)); args.Result = outputMesh; }; worker.RunWorkerCompleted += (sender, args) => { var resultMesh = (WorkingMesh)args.Result; resultMesh.ApplyToMesh(simplifiedMesh); simplifiedMesh.RecalculateBounds(); }; worker.RunWorkerAsync(); } var lod = lods[l]; lod.renderers = lodRenderers.ToArray(); lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(0.5f, l + 1); lods[l] = lod; } lodGroup.ForceLOD(0); lodGroup.SetLODs(lods.ToArray()); lodGroup.RecalculateBounds(); lodGroup.ForceLOD(-1); var prefab = PrefabUtility.GetPrefabParent(go); if (prefab) { var lodsAssetPath = GetLODAssetPath(prefab); if (File.Exists(lodsAssetPath)) { meshes.ForEach(m => AssetDatabase.AddObjectToAsset(m, lodsAssetPath)); } else { ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath); } } } }
void GenerateLODs() { int maxLOD = 1; var go = gameObject; var hlodLayer = LayerMask.NameToLayer(HLODLayer); var lodGroup = go.GetComponent <LODGroup>(); if (lodGroup) { var lods = new LOD[maxLOD + 1]; var lod0 = lodGroup.GetLODs()[0]; lod0.screenRelativeTransitionHeight = 0.5f; lods[0] = lod0; var meshes = new List <Mesh>(); var totalMeshCount = maxLOD * lod0.renderers.Length; for (int l = 1; l <= maxLOD; l++) { var lodRenderers = new List <MeshRenderer>(); foreach (var mr in lod0.renderers) { var mf = mr.GetComponent <MeshFilter>(); var sharedMesh = mf.sharedMesh; var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l), k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform; lodTransform.gameObject.layer = hlodLayer; lodTransform.SetPositionAndRotation(mf.transform.position, mf.transform.rotation); lodTransform.localScale = mf.transform.lossyScale; lodTransform.SetParent(mf.transform, true); var lodMF = lodTransform.GetComponent <MeshFilter>(); var lodRenderer = lodTransform.GetComponent <MeshRenderer>(); lodRenderers.Add(lodRenderer); EditorUtility.CopySerialized(mf, lodMF); EditorUtility.CopySerialized(mf.GetComponent <MeshRenderer>(), lodRenderer); var simplifiedMesh = new Mesh(); simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l); lodMF.sharedMesh = simplifiedMesh; meshes.Add(simplifiedMesh); var meshLOD = new MeshLOD(); meshLOD.inputMesh = sharedMesh; meshLOD.outputMesh = simplifiedMesh; meshLOD.quality = Mathf.Pow(0.5f, l); meshLOD.meshSimplifierType = meshSimplifierType; } var lod = lods[l]; lod.renderers = lodRenderers.ToArray(); lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(0.5f, l + 1); lods[l] = lod; } lodGroup.ForceLOD(0); lodGroup.SetLODs(lods.ToArray()); lodGroup.RecalculateBounds(); lodGroup.ForceLOD(-1); #if UNITY_2018_2_OR_NEWER var prefab = PrefabUtility.GetCorrespondingObjectFromSource(go); #else var prefab = PrefabUtility.GetPrefabParent(go); #endif if (prefab) { var assetPath = AssetDatabase.GetAssetPath(prefab); var pathPrefix = Path.GetDirectoryName(assetPath) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(assetPath); var lodsAssetPath = pathPrefix + "_lods.asset"; ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath); } } }