- Home /
Editing a LODGroup from script
Hello Unity Answers!
My current script is raising this exception whenever I try to set LOD levels: "SetLODs: Attempting to set LOD where the screen relative size is greater then or equal to a higher detail LOD level."
Before I post the actual script, what is supposed to happen, and what is actually happening?
The script is supposed to create a new LODGroup out of a selection of GameObjects. The GameObjects have to be named MyGameObjectName_LOD0, MyGameObjectName_LOD1, etc. This works 100% fine as long as you only have one GameObject selected. When selecting a 2nd or more GameObjects the exception above is raised.
private void CreateLodGroup()
{
GameObject[] sel = Selection.gameObjects;
if (sel == null || sel.Length == 0)
{
Debug.LogError("FAILED -> You must have at least 1 GameObject selected!");
return;
}
var lods = new SortedList<int, GameObject>();
string mainName = null;
foreach (GameObject o in sel)
{
string oName = o.name;
Match regexMatch = Regex.Match(oName, @"(.*)_LOD([0-9])");
if (regexMatch.Success)
{
string oMainName = regexMatch.Groups[1].ToString();
int oIndex = Convert.ToInt32(regexMatch.Groups[2].ToString());
if (mainName == null || oMainName == mainName)
{
mainName = oMainName;
}
else
{
Debug.LogError("FAILED -> The GameObject main names aren't matching! Expected main name \"" +
mainName + "\", got \"" + oMainName + "\"!");
return;
}
if (!lods.ContainsKey(oIndex))
{
lods.Add(oIndex, o);
}
else
{
Debug.LogError("FAILED -> The LOD object with the ID " + oIndex +
" exists twice! Make sure to avoid duplicates!");
return;
}
}
else
{
Debug.LogError("FAILED -> GameObject \"" + oName +
"\" was in the wrong name format to be added as a LOD object!");
return;
}
}
int lfIndex = lods.Count - 1;
while (lfIndex >= 0)
{
if (lods.ContainsKey(lfIndex))
{
lfIndex--;
}
else
{
Debug.LogError("FAILED -> LOD level " + lfIndex + " could not be found!");
return;
}
}
var lodObject = new GameObject(mainName);
var lodGroup = lodObject.AddComponent<LODGroup>();
var lodLevels = new LOD[lods.Count];
foreach (var lod in lods)
{
float lodSize = (float)Math.Round(1d / lods.Count, 1);
Debug.Log("LOG -> Size=" + lodSize);
Renderer[] renderers = lod.Value.GetComponentsInChildren<Renderer>();
if (renderers == null || renderers.Length == 0)
{
Debug.LogWarning("WARNING -> No Renderers for LOD level " + lod.Key + " found!");
}
lod.Value.transform.SetParent(lodObject.transform);
LOD lodLevel = new LOD(lodSize, renderers);
lodLevels[lod.Key] = lodLevel;
}
lodGroup.SetLODs(lodLevels); // <!!> The exception is raised from calling this method! <!!>
}
I suspect that the exception is raised by a "bad" screenRelativeTransitionHeight (Documentation: http://docs.unity3d.com/). However I have tried out multiple values, all without success. I am kinda stuck here, so Id really appreciate any help possible c:
Thanks, 7BiT.psycho
Btw: The script is being executed in the editor.
Perhaps you could just simulate the editor's script for creating them? or have a look through the script to see https://github.com/$$anonymous$$attRix/UnityDecompiled/blob/master/UnityEditor/UnityEditor/LODGroupEditor.cs (but you should probably decompile the current version of UnityEditor.dll, rather than whatever version that is)
And if you do have it set up, please update as I'd find it pretty convenient myself...
Edit: in order to actually do that, you might have to copy quite a bit of unity's codebase, though
Answer by CatyRaiu · May 21, 2020 at 10:05 AM
It worked for me!
LODGroup group = LOD_Parent.GetComponent<LODGroup>();
LOD[] lod_s_exi = group.GetLODs();
for ( int i = 0; i < lod_s.Count; i++ )
{
MeshRenderer[] renderers = lod_s[i].GetComponentsInChildren<MeshRenderer>();
if ( renderers == null || renderers.Length == 0 )
{
print("No rendererFinded");
}
LOD lod = new LOD(lod_s_exi[i].screenRelativeTransitionHeight, renderers);
lod_s_exi[i] = lod;
}
group.SetLODs(lod_s_exi);
And BTW ! Thanks for your post! Helped me a lot because in this matter i was like a tree....Tkx again!
Hey @CatyRaiu ,
sorry I don't get this here. (Maybe I'm overseeing the elephant in the room). I'm not THAT famliar with setting LDS programmaticly but here's my Code (extracted from a plugin). Could you please tell me what's wrong with it because I get the exact same error, like @a7BiT-psycho
void SetupLods(GameObject gameObject)
{
// Set up LODs
foreach (MathWorks.LodImportData lodImportData in gameObject.GetComponentsInChildren<MathWorks.LodImportData>())
{
GameObject lodGameObject = lodImportData.gameObject;
int numThresholds = lodImportData.LodThresholds.Count;
LODGroup lodGroup = lodGameObject.AddComponent<LODGroup>();
LOD[] lods = new LOD[numThresholds];
for (int j = 0; j < numThresholds; j++)
{
float threshold = lodImportData.LodThresholds[j] / 100.0f; // Convert from percentage
Renderer[] renderers = lodGameObject.transform.GetChild(j).GetComponentsInChildren<Renderer>();
lods[j] = new LOD(threshold, renderers);
}
lodGroup.SetLODs(lods);
lodGroup.RecalculateBounds();
// Delete temp data
UnityEngine.Object.DestroyImmediate(lodImportData);
}
}