Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question [Feedback] Grabbing the raw LOD[] from an LODGroup

Discussion in 'Editor & General Support' started by malkere, Jan 8, 2021.

  1. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    Feedback addition: Please Unity, don't clamp LODs from 0-1. There are many use cases where 100%+ screen use is still a very distant object.

    Original post:
    If you switch the inspector to debug mode you can see and edit directly the LOD[] in an LODGroup that is called "LODs". However, this variable is not accessible in anyway that I can find, leaving you the only option to set LODs via SetLODs(). However, SetLODs() clamps the values from 0-1, making values greater than 1.0 impossible to set via script, nor via the normal inspector.

    Again, this is something that you can do via debug, and something that is quite normal in other engines, for example with large trees, that will reach 1.0 even though you are still 50m away.

    Is anyone smarter than me aware of a way to access the LODs private variable "LODs" in the LODGroup component in runtime, perhaps via reflection? I can't figure it out.

    Cheers.
     
    Last edited: Jan 8, 2021
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,890
    If it's not a visible field in C# then you're stuck with basically three options:
    1. Reflection will almost definitely work, assuming there is a raw array field on the object somewhere
    2. Some kind of custom precompiled CIL module which skips the reflection part and just knows where the field is on the LODGroup object. I've seen @Bunny83 do this for WaitForSeconds reuse in a thread a while back. That's probably only necessary if you need this to be really performant for some reason. It sounds like an editor script so probably not?.
    3. Submit this as a bug and/or feature request and wait for Unity to get around to it (good luck).
     
    malkere likes this.
  3. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    upload_2021-1-8_13-32-46.png

    If you check it out in debug mode you can definitely see it. Unfortunately I'm not well versed in reflection, and my efforts have not yet awarded me access. I was starting to think maybe the array was C++ side, but you can input the numbers directly via the debug inspector and they work as expected. Even though the LODGroup editor drawer isn't capable of understanding it:

    upload_2021-1-8_13-34-57.png

    Could anyone provide an example of how to access it via reflection? I'm searching and trying different methods to do so in the meantime.

    additional: I am looking to do this in runtime not in the editor, but it does not need to be performant. I'm just trying to add settings for tree LODGroup control in runtime without having to mess with the universal bias settings.
     
  4. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    I suppose if they're editable in the debug inspector they're not private actually are they...
    I've tried creating an extentsion, but it doesn't see anything:

    upload_2021-1-8_14-49-9.png

    I've tried scanning the fields with reflection, but it doesn't seem to find anything either. Though I admit I don't understand what all of the different BindingFlags are used for. Maybe there is a specific combination needed for the LODs variable? I've tried nonpublic and public but can't locate it...

    upload_2021-1-8_14-51-1.png

    peaking at the editor C# script there is this for LODGroups:

    m_LODs = serializedObject.FindProperty("m_LODs");

    I just can't figure out how to get to it outside of the editor...
     
    Last edited: Jan 8, 2021
  5. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,890
    malkere likes this.
  6. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    I'm confused how the editor interacts with it so smoothly if it is indeed on the C++ side, but I too am already beyond the limits of my knowledge how this kind of stuff works.

    I'll add the feedback tag for now, and ask that Unity not clamp 100% as the maximum screen usage.
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,919
    Right, like most of the built-in components and most of their data only exists on the native side. The inspector always works with the serialized data. Serialization is done on the native side, even for your managed classes.

    Yes, if the classes do not have any methods that can access / change that data, you can not use reflection. Reflection can only use things that are actually there but usually unavailable due to visibility restrictions.

    I haven't tried it but I guess Unity's JsonUtility could help here. Since it can also handle serialized data on the native side you could try serializing the data to json, modify the json and deserialize with JsonOverride to "patch" the instance. It's not guaranteed to work as it depends on how well this built-in component's data is supported by the JsonUtility.

    I still don't have a Unity installation at hand (still not home ^^) so I can't test this. Though I never really used LOD groups in Unity to this day ^^.
     
    malkere likes this.
  8. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    Thanks for the reply Bunny83, always appreciate seeing your name show up.

    I started as an amateur and so pretty much still am on despite having been developing full-time for 3 years now. My game is fully procedural though, so I lose of the options to fine tune and bake things together. Do you have any suggestions for an alternative to LOD groups?

    I'll try out the JSON method though, I understand what you're getting at with that explanation.
     
  9. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    Well... JsonUtility flat out complains that it can't touch engine objects.

    Code (CSharp):
    1.         UnityEditor.SerializedObject serializedObject = new UnityEditor.SerializedObject(lGroup);
    2.         UnityEditor.SerializedProperty serializedProperty = serializedObject.FindProperty("m_LODs");
    3.         for (int i = 0; i < serializedProperty.arraySize; i++) {
    4.             UnityEditor.SerializedProperty lod = serializedProperty.GetArrayElementAtIndex(i);
    5.             UnityEditor.SerializedProperty lodHeight = lod.FindPropertyRelative("screenRelativeHeight");
    6.             Debug.Log(lodHeight.floatValue);
    7.         }
    This prints out the values, but it's all editor script... will keep playing with it...

    Perhaps a CreateDelegate approach could work?
     
  10. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,919
    Well, if that's the case that's unfortunate. Those are the little things I don't like about Unity ^^. It's well made besides some poor design decisions. Though a lot of features have some not so obvious inconsistencies here and there. This makes a lot of features to feel only 90% or 95% complete which is kinda sad ^^. The JsonUtility (afaik) does work with all built in components and most UnityEngine.Object derived built in types. Though maybe they only support those explicitly where they through it may be useful.

    As I said I never used the LOD system of Unity. However peaking into the scripting reference of the LODGroup component shows that there's a method to get and set an array of the "LOD" struct. I guess it contains what you're after or does it? So no special magic would be involved here ^^.
     
  11. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    The problem is that the method to set the LOD array loops through it and clamps the values to 0-1 =[ If I could bypass the built-in method and just alter the array... I was trying to make it support trees and larger objects that can go beyond 100% screen usage, but I've given up. Them being structs makes it that much less likely too. Thanks for the ideas though.
     
  12. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,919
    Well if that's really the case and you can go beyond the range 0 - 1 in the inspector, you should file a bug report. It certainly won't fix your issues now because bug reports usually have a long way until they may finally result in a change in a future version. Though such inconsistencies should not exist and should be fixed. Of course they could fix it in two different ways. Either they remove the clamping when using SetLODs or they could add the clamp to the inspector ^^. So if you file a bug report you should explain why it would be a good idea to do it this way and not the other.

    You can file a bug report inside the Unity editor from the "Help" main menu point.
     
    Last edited: Jan 11, 2021
    malkere likes this.