Search Unity

Batch set lod distances script.

Discussion in 'Formats & External Tools' started by koirat, Jun 29, 2020.

  1. koirat

    koirat

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

    StenCG

    Joined:
    Mar 26, 2015
    Posts:
    66
    Thx! But in 2019.4 have compile errors:

    Assets\Editor\BatchSetLodGroupWindow.cs(83,40): error CS0103: The name 'ObjectUtils' does not exist in the current context

    Assets\Editor\BatchSetLodGroupWindow.cs(103,49): error CS1061: 'float[]' does not contain a definition for 'Last' and no accessible extension method 'Last' accepting a first argument of type 'float[]' could be found

    Assets\Editor\BatchSetLodGroupWindow.cs(117,87): error CS1061: 'float[]' does not contain a definition for 'Last' and no accessible extension method 'Last' accepting a first argument of type 'float[]' could be found
     
    koirat likes this.
  3. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,074
    Thank you for your input. I have repaired the script should be compiling now.

    Next time please quote or send a private message, I don't usually check my old messages.
     
    kotoezh, Andreas12345 and StenCG like this.