Unit Attributes

Generally, nobody describes something as being 75 m/s fast. They describe it as 270 kph! Or 167 mph if you're so inclined.

Enter the Unit attribute. Code and edit the values that make the most sense to you. The attribute allows you to define a 'base' and a 'display' unit:

[Unit(Units.MetersPerSecond, Units.KilometersPerHour)]
public float Speed;

Here, we use MetersPerSecond for the base unit. The speed value in the code is, therefore, always in meters per second. And by setting KilometersPerHour for the display unit, the speed value is converted when drawn in the inspector to, well, kilometers per hour. Now, when you type 270 into the field, it gets converted to 75 m/s. Or enter '167 mph', which also converts to ~75 m/s.

As an alternative example, you can use a smaller display unit:

[Unit(Units.Meter, Units.Centimeters)]
public float SuspensionLength;

Sometimes, making small, minor adjustments to a value can be challenging, especially when dragging with the mouse. That is the case in the above example, and therefore by displaying the unit as centimeters, it is much easier to make minor adjustments. You might later decide that centimeters are too granular for your liking and switch to millimeters - all without affecting the rest of your code.

Unsure, which units suit the editor? Easy: Define the base unit and change how it's displayed in the inspector by right-clicking.

[Unit(Units.Kilogram)]
public float Weight;

Here, we've just defined the weight as being kilograms. And, as we're working with the inspector, we can quickly change between other weight units as we desire. And, of course, type in weight in another unit, for example, pounds, and have the inspector convert that for us to kilograms. That is a godsend if you work on any simulation or use real-life values.

An excellent use for units is to show debug values while play-testing. In the following example, we grab the velocity of a rigidbody and convert it to kilometers per hour for the inspector. It gives an easy-to-read value to help you know what the code is doing, using the DisplayAsString option to show the value only as text.

public Rigidbody myRigidbody;

[ShowInInspector, HideInEditorMode, Units(Units.MetersPerSecond, Units.KilometersPerHour, DisplayAsString = true)]
public float DebugSpeed => myRigidbody.velocity.magnitude;

Optionally, there is also the ForceDisplayUnit option to prevent users from changing the displayed unit in the inspector.

What if Odin doesn't have the unit you need? You can add it yourself! In this example, we'll add a custom Odin unit. We'll define 1 Odin as 42 meters.

[InitializeOnLoadMethod]
public static void AddCustomUnit()
{
	UnitNumberUtility.AddCustomUnit(
		name: "Odin",
		symbols: new string[] { "odin" },
		unitCategory: UnitCategory.Distance,
		multiplier: 1m / 42m);
}

// Use the custom unit by referencing it by name.
[Unit(Units.Meter, "Odin")]
public float Odins;

Unity's InitializeOnLoadMethod calls a method when the editor starts with UnitNumberUtility.AddCustomUnit, we add our Odin unit. We only add a single symbol, "odin", here for simplicity, but you can add more. We use the Distance category so we can convert to other distance units. Odin will only convert between units of the same category. Finally, we set the multiplier as 1/42; the multiplier needed to convert 1 meter to Odin. See the UnitNumberUtility documentation for more details

Finally, we have some caveats. Due to the nature of floating points and conversions between floats, double and decimals, precision can become an issue for you, especially if you want to convert from really high to very low values or vice-versa. Converting 1000 light years to nanometers is going to be iffy at best. Keep that in mind.

Enjoy.

public class UnitsExamples : MonoBehaviour
{
	[Unit(Units.MetersPerSecond, Units.KilometersPerHour)]
	public float Speed;

	[Unit(Units.Meter, Units.Centimeter)]
	public float SuspensionLength;

	[Unit(Units.Kilogram)]
	public float Weight;
	
	public Vector3 Velocity; // Stand in for rigidbody.velocity
	
	// [HideInEditorMode] // Use to show the debug value only in play mode.
	[ShowInInspector, Unit(Units.MetersPerSecond, Units.KilometersPerHour, DisplayAsString = true)]
	public float DebugSpeed => Velocity.magnitude;

    [InitializeOnLoadMethod]
    public static void AddCustomUnit()
    {
		UnitNumberUtility.AddCustomUnit(
			name: "Odin",
			symbols: new string[] { "odin" },
			unitCategory: UnitCategory.Distance,
			multiplier: 1m / 42m);
    }

    // Use the custom unit by referencing it by name.
    [Unit(Units.Meter, "Odin")]
    public float Odins;
}