Hey there!
Recently I needed to store floats as integers and vice versa (used it to easily xor floats in my Anti-Cheat Toolkit) and I came across few ways of doing this.
Unsafe pointers – fastest one:
public unsafe int FloatToInt(float value)
{
return *(int*)&value;
}
public unsafe float IntToFloat(int value)
{
return *(float*)&value;
}
Easy, right?
Please, note, it requires /unsafe compiler option. To leverage unsafe operations in unity, you have two commonly used options to choose from:
1. Use it in a separate dll, compiled with /unsafe option.
2. Set /unsafe option right in your project using “Global Custom Defines”, putting it in .rsp file in your Assets/ root. See bottom of this page for details.
And keep in mind unsafe code is not supported in some build targets, like Web Player and Flash Player.
Unions (Explicitly layouted structs) – slower than pointers, but works in Web Player (not in Flash Player, d’oh!):
[StructLayout(LayoutKind.Explicit)]
internal struct FloatIntUnion
{
[FieldOffset(0)]
public float f;
[FieldOffset(0)]
public int i;
}
public int FloatToInt(float value)
{
var u = new FloatIntUnion();
u.f = value;
return u.i;
}
public float IntToFloat(int value)
{
var u = new FloatIntUnion();
u.i = value;
return u.f;
}
Pretty easy to use, safe and works on more build targets comparing to pointers.
Note [StructLayout(LayoutKind.Explicit)] attribute is used here in conjunction with [FieldOffset(*)] attribute. It allows you to set each struct field position in memory explicitly and read data stored there.
BitConverter class – pretend to be slowest:
public int FloatToInt(float value)
{
return BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
}
public float IntToFloat(int value)
{
return BitConverter.ToSingle(BitConverter.GetBytes(value), 0);
}
Safest one though (works even in Flash Player).
I should mention there are so-called “safe pointers” in C#, used through Marshal class, but they are pretty complicated, require unmanaged memory allocations and constant control on memory at all (C# developers are usually rely on GC and do not bother on allocations), so I’ll not post Marshal review here for now, these 3 methods I described are usually enough for the types conversion.
I hop I’ll have some time to make performance tests on these methods in latest Unity 4.3 later and post results with tests sourcers here (in another blog post).
Questions? Ask in comments!
Found a typo? Please, highlight it and press Shift + Enter or click here to inform me!