Search Unity

  1. Unity 2019.4 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  3. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

Batch set lod distances script.

Discussion in 'External Tools' started by koirat, Jun 29, 2020 at 3:00 PM.

  1. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    229
    Why I made it:
    I made it because I have downloaded some models/prefabs from asset store and distances set on LODGroup were completely unacceptable. Also there were a lot of prefabs so doing it all manually would be a waste of time.


    What does it do:
    It basically finds all prefabs that make use of LodGroups and set it's distances.

    What it does not do:
    It will not add additional lod levels or do anything with the renderers.
    It only mess around with distances.

    How to run:
    Personally I got this script in Assets/Editor/EditorExtensions
    You run it by menu Tools->BatchSetLodGroups

    You select a folder set weights to your liking and click apply. You cannot stop the process, there is no progress bar, and it takes a while sometime.

    Additional info:
    The script is very simple and not very pretty. I might change some things in the future but don't count on it. Feel free to modify it or post a comment.
    Thank you.

    THE SOURCE !!!:
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using UnityEditor;
    5. using UnityEngine;
    6.  
    7. public class BatchSetLodGroupWindow : EditorWindow{
    8.  
    9.     bool includeSubdirectories = true;
    10.     LODFadeMode fadeMode = LODFadeMode.None;
    11.  
    12.     float cullRatio = 0.01f;
    13.  
    14.     public float[] lodWeights = new float[] { 0.6f, 0.3f, 0.1f };
    15.  
    16.     string path = string.Empty;
    17.  
    18.     [MenuItem("Tools/BatchSetLodGroups")]
    19.     public static void ShowWindow() {
    20.         //Show existing window instance. If one doesn't exist, make one.
    21.         EditorWindow.GetWindow(typeof(BatchSetLodGroupWindow));
    22.     }
    23.  
    24.     void OnGUI() {
    25.  
    26.         GUILayout.Label("LODGroup Settings", EditorStyles.boldLabel);
    27.  
    28.         EditorGUILayout.BeginHorizontal();
    29.         EditorGUILayout.PrefixLabel("Select Directory");
    30.         if (GUILayout.Button("Browse")) {
    31.             path = EditorUtility.OpenFolderPanel("Select Directory", "", "");
    32.         }
    33.         EditorGUILayout.EndHorizontal();
    34.  
    35.         EditorGUILayout.BeginHorizontal();
    36.         EditorGUILayout.PrefixLabel("Current Path");
    37.         EditorGUILayout.LabelField(path);
    38.         EditorGUILayout.EndHorizontal();
    39.  
    40.         includeSubdirectories = EditorGUILayout.Toggle("Include Subdirectories", includeSubdirectories);
    41.  
    42.         EditorGUILayout.BeginHorizontal();
    43.         EditorGUILayout.PrefixLabel("Fade Mode");
    44.         fadeMode = (LODFadeMode)EditorGUILayout.EnumPopup((Enum)fadeMode);
    45.         EditorGUILayout.EndHorizontal();
    46.  
    47.         EditorGUILayout.BeginHorizontal();
    48.         EditorGUILayout.PrefixLabel("Cull Ratio (0.01 = 1%)");
    49.         cullRatio = EditorGUILayout.FloatField(cullRatio);
    50.         EditorGUILayout.EndHorizontal();
    51.  
    52.         EditorGUILayout.LabelField("LOD Level Weights (will be normalized to 1)");
    53.  
    54.         ScriptableObject target = this;
    55.         SerializedObject so = new SerializedObject(target);
    56.         SerializedProperty prop = so.FindProperty(nameof(lodWeights));
    57.         EditorGUILayout.PropertyField(prop, true); // True means show children
    58.         so.ApplyModifiedProperties(); // Remember to apply modified properties
    59.  
    60.         if (GUILayout.Button("Apply")) {
    61.             if (!string.IsNullOrWhiteSpace(path)) {
    62.  
    63.                 PerformActionOnPrefab(path, this.includeSubdirectories, GetSetLoadGroup(fadeMode,cullRatio, this.lodWeights));
    64.             }
    65.         }
    66.  
    67.         Func<GameObject, bool> GetSetLoadGroup(LODFadeMode fadeMode,float cullRatio, float[] lodWeights) {
    68.             return x => SetLodGroupInner(x, fadeMode,cullRatio, lodWeights);
    69.         }
    70.  
    71.         bool SetLodGroupInner(GameObject prefab, LODFadeMode fadeMode,float cullRatio, float[] lodWeights) {
    72.  
    73.             if (lodWeights == null || lodWeights.Length == 0) return false;
    74.  
    75.             List<LODGroup> lodGroups = ObjectUtils.FindComponentsDown<LODGroup>(prefab.transform);
    76.  
    77.             if (lodGroups == null || lodGroups.Count <= 0) {
    78.                 return false;
    79.             }
    80.  
    81.             for (int i = 0; i < lodGroups.Count; i++) {
    82.                 LODGroup lodGroup = lodGroups[i];
    83.  
    84.                 lodGroup.fadeMode = fadeMode;
    85.                 LOD[] lods = lodGroup.GetLODs();
    86.  
    87.                 float weightSum = 0;
    88.                 for (int k = 0; k < lods.Length; k++) {
    89.  
    90.                     if (k >= lodWeights.Length) {
    91.                         weightSum += lodWeights.Last();
    92.                     } else {
    93.                         weightSum += lodWeights[k];
    94.                     }
    95.                 }
    96.  
    97.  
    98.                 float maxLength = 1 - cullRatio;
    99.                 float curLodPos = 1;
    100.                 for (int j = 0; j < lods.Length; j++) {
    101.  
    102.                     float weight = j < lodWeights.Length ? lodWeights[j] : lodWeights.Last();
    103.  
    104.                     float lengthRatio = weightSum != 0 ? weight / weightSum : 1;
    105.  
    106.                     float lodLength = maxLength * lengthRatio;
    107.                     curLodPos = curLodPos - lodLength;
    108.  
    109.                     lods[j].screenRelativeTransitionHeight = curLodPos;
    110.                 }
    111.  
    112.  
    113.                 lodGroup.SetLODs(lods);
    114.             }
    115.  
    116.             return true;
    117.         }
    118.     }
    119.  
    120.  
    121.     //action: input prefab output should save to prefab
    122.     void  PerformActionOnPrefab(string path, bool includeSubdirectories,Func<GameObject,bool> action) {
    123.         string[] files = Directory.GetFiles(path,"*.prefab", includeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
    124.  
    125.         foreach (var file in files) {
    126.             GameObject prefabGO = PrefabUtility.LoadPrefabContents(file);
    127.  
    128.             if (prefabGO != null) {
    129.                 action(prefabGO);
    130.  
    131.                 PrefabUtility.SaveAsPrefabAsset(prefabGO, file);
    132.                 PrefabUtility.UnloadPrefabContents(prefabGO);
    133.             }
    134.         }
    135.  
    136.     }
    137.  
    138. }
     
unityunity