Get range of public variable

Script A is a controller that holds a declaration for a float with a range:

[Range(0, 135f)]
public float RotatingPart;

Script B initialises a UI Slider to control RotatingPart and handles the OnValueChanged. This is working.
However, I can’t figure out how to automatically set the range of the Slider to match the Float’s range. Is there a way to read this value?

You’d need to use reflection to gleam this data from the field, if this meta data is even compiled into a built game.

If ‘135f’ is always going to be constant, I’d just make a constant value somewhere to set that.

i would assume its not possible to get at runtime, since the range is only used by the editor it does not even exist in the SerializedObject. If i needed that data at runtime, i would make my own struct type that stores the min, max and value.

You say that, but from what I can tell the Attributes aren’t surrounded by #if UNITY_EDITOR pre-processors, nor are they using the System.Diagnostics.Conditional attribute to conditionally compile them and they’re in the regular UnityEngine assembly.

You’d have to test, but they might actually get built into the game from what I can see.

they might, but would require reflection to access, yeah looked at the code, pretty sure you can get them with reflection if wanted just like you would one of your own custom attributes.

Thanks for the suggestion. I’ve tried to access the field in A from script B using reflection and it does find it.

FieldInfo myFieldInfo = myClassType.GetField("RotatingPart");

I’m now stuck on how to access the range attributes of this field. Both here and with GetProperty the following popped up but does not work:

... Range.{StartAt, EndAt}

How to get a handle on the Range as it’s not a variable or uniquely named field?

i can give a better example once i get to my work computer, but once you got your field, property or method, you can call GetCustomAttribute on it passing RangeAttribute for T.

keep in mind reflection is pretty slow, so i would get it once and cache the information.

var rangeAttr = myFieldInfo.GetCustomAttribute<RangeAttribute>();

if (rangeAttr != null)
{
    Debug.Log($"Range is {rangeAttr.min} - {rangeAttr.max}");
}

You probably want to read up on how to get attributes from something: Retrieving Information Stored in Attributes - .NET | Microsoft Learn

In any case Reflection should be your last choice when all else fails. If the value of ‘135f’ is unchanging, just make it a const field.

I see your point. To provide some background: these GO’s containing script A are delivered and maintained by a third party. Hence we prefer not to edit these scripts. We could however ask them to store the min/max values in separate variables from now on.

I mean you wouldn’t have to edit the scripts. You could store them as static or const values anywhere else.

Reflection is the only way to access attributes at runtime as they are pure metadata. I also wouldn’t recommend to use such attributes for storing class relevant data. As spiney suggested, just use a constant like this:

    public const float RotatingPartMax = 135f;
    [Range(0, RotatingPartMax)]
    public float RotatingPart;

Now you can simply use that constant wherever you need it inside your code.