Unity 编辑器开发实战【MenuItem】- 批量删除场景中的LOD Group,保留最高层次细节

举报
CoderZ1010 发表于 2022/09/25 04:39:49 2022/09/25
【摘要】 如果场景中包含大量的LOD Group组件,我们不想要使用时,手动依次删除需要耗费大量时间,本文介绍如何编写一个批量删除场景中LOD Group组件,并且只保留最高层次细节的物体的工具。 实现思路: 1.使用MenuItem制作一个功能菜单; 2.调用功能时,弹出窗口提醒确认删除场景中的LOD Group组件; 3.如果物体...

如果场景中包含大量的LOD Group组件,我们不想要使用时,手动依次删除需要耗费大量时间,本文介绍如何编写一个批量删除场景中LOD Group组件,并且只保留最高层次细节的物体的工具。

实现思路:

1.使用MenuItem制作一个功能菜单;

2.调用功能时,弹出窗口提醒确认删除场景中的LOD Group组件;

3.如果物体属于Prefab,不能进行销毁操作,因此还要确认是否进行Prefab Unpack;

4.遍历场景中的所有LOD Group组件;

5.遍历LOD Group中的LOD结构数组;

6.遍历每一个LOD结构中的Renderer组件,销毁其所在物体;

7.LOD Group组件遍历之后将其销毁。

代码如下:


  
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEngine.SceneManagement;
  4. namespace SK.Framework
  5. {
  6. /// <summary>
  7. /// LOD工具
  8. /// </summary>
  9. public class LODTool : Editor
  10. {
  11. [MenuItem("SKFramework/Tools/LOD/Delete")]
  12. private static void Open()
  13. {
  14. //弹出进行删除操作的提醒窗口
  15. bool confirm = EditorUtility.DisplayDialog("提醒", "是否确定删除场景中所有的LOD Group组件,只保留最高层次的细节", "确定", "取消");
  16. //点击取消则return
  17. if (!confirm) return;
  18. //弹出窗口 询问是否执行Prefab Unpack操作
  19. bool unpackPrefab = EditorUtility.DisplayDialog("确认", "如果目标物体属于Prefab预制体,执行Prefab Unpack操作还是跳过它?", "Unpack", "Skip");
  20. //获取当前场景中的所有根物体
  21. GameObject[] rootObjs = SceneManager.GetActiveScene().GetRootGameObjects();
  22. //遍历所有根物体
  23. for (int i = 0; i < rootObjs.Length; i++)
  24. {
  25. GameObject rootObj = rootObjs[i];
  26. //在根物体及子物体身上查找所有LOD Group组件
  27. LODGroup[] groups = rootObj.GetComponentsInChildren<LODGroup>(true);
  28. //遍历所有LOD Group组件
  29. for (int j = 0; j < groups.Length; j++)
  30. {
  31. LODGroup group = groups[j];
  32. GameObject obj = group.gameObject;
  33. //获取LOD Group中的所有LOD结构
  34. LOD[] lods = group.GetLODs();
  35. if (lods.Length < 2) continue;
  36. //遍历LOD结构 索引从1开始 保留最高层次的细节
  37. for (int l = 1; l < lods.Length; l++)
  38. {
  39. LOD lod = lods[l];
  40. //遍历LOD中的Renderer组件
  41. for (int n = 0; n < lod.renderers.Length; n++)
  42. {
  43. Renderer renderer = lod.renderers[n];
  44. if (renderer == null) continue;
  45. //如果Renderer组件不为空 获取其挂载的物体
  46. GameObject target = renderer.gameObject;
  47. //物体不为空,进行销毁
  48. if (target != null)
  49. {
  50. //如果目标物体属于Prefab预制体
  51. if (PrefabUtility.IsPartOfAnyPrefab(target))
  52. {
  53. if (unpackPrefab)
  54. {
  55. //获取Prefab预制体根级
  56. var prefabRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(target);
  57. //Prefab Unpack Completely
  58. PrefabUtility.UnpackPrefabInstance(prefabRoot, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
  59. }
  60. else continue;
  61. }
  62. //弹出进度条
  63. EditorUtility.DisplayProgressBar("LOD deleting...", $"{rootObj.name}/{obj.name}/{target.name}", (i + 1) / rootObjs.Length);
  64. DestroyImmediate(target);
  65. }
  66. }
  67. }
  68. Debug.Log($"删除{group.name}的LOD Group组件.");
  69. //删除LOD Group组件
  70. DestroyImmediate(group);
  71. EditorUtility.SetDirty(obj);
  72. }
  73. }
  74. //清除进度条
  75. EditorUtility.ClearProgressBar();
  76. }
  77. }
  78. }

文章来源: coderz.blog.csdn.net,作者:CoderZ1010,版权归原作者所有,如需转载,请联系作者。

原文链接:coderz.blog.csdn.net/article/details/123637965

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。