ConstExpressionForUnity
Library for compile-time function execution in Unity.
com.katuusagi.constexpressionforunity 
Install via UPM
Add to Unity Package Manager using this URL
https://www.pkglnk.dev/constexpressionforunity.git?path=packages README Markdown
Copy this to your project's README.md
## Installation
Add **ConstExpressionForUnity** to your Unity project via Package Manager:
1. Open **Window > Package Manager**
2. Click **+** > **Add package from git URL**
3. Enter:
```
https://www.pkglnk.dev/constexpressionforunity.git?path=packages
```
[](https://www.pkglnk.dev/pkg/constexpressionforunity)README
ConstExpressionForUnity
Summary
This library "ConstExpressionForUnity" is a compile-time computation library.
With ConstExpression, you can find a constant computation process at compile-time and embed only the result of the computation in your code.
By using it, you can implement high-load processes such as hash computation and de Brownian sequence computation at zero cost.
Also included in the library is StaticExpression, a runtime pre-computation function.
With StaticExpression, the constant computation process is performed statically.
System Requirements
| Environment | Version |
|---|---|
| Unity | 6000.0.51f1 |
| .Net | 4.x, Standard 2.1 |
Example of ConstExpression execution
Implementation Example
using Katuusagi.ConstExpressionForUnity;
public static class MyConstExpression
{
[ConstExpression]
public static int Add(int l, int r)
{
return l + r;
}
[StaticExpression]
public static int Add2(int l, int r)
{
return l + r;
}
}
using UnityEngine;
public static class Test
{
public static void Run()
{
Debug.Log(MyConstExpression.Add(100, 200));
Debug.Log(MyConstExpression.Add2(100, 200));
}
}
Post-compilation code(with ILSpy)
using Katuusagi.ConstExpressionForUnity.Generated;
using UnityEngine;
public static class Test
{
public static void Run()
{
Debug.Log((object)300);
Debug.Log((object)$$StaticTable.$0);
}
}
Thus, unnecessary run-time computation can be omitted and only the results of the computation can be embedded in the code.
Performance
Measurement code on the editor
Test Code.
Multiple prime number calculations by Sieve of Eratosthenes.
Result
| Process | Processing Time |
|---|---|
| CalcPrime_ConstExpression | 0.0138 ms |
| CalcPrime_StaticExpression | 0.0201 ms |
| CalcPrime_Raw | 17.98335 ms |
Since the computation itself disappears and only the result of the computation is returned, the cost is almost negligible.
How to install
Installing ILPostProcessorCommon
Refer to ILPostProcessorCommon v2.4.1 for installation.
Installing ConstExpressionForUnity
- Open [Window > Package Manager].
- click [+ > Add package from git url...].
- Type
https://github.com/Katsuya100/ConstExpressionForUnity.git?path=packagesand click [Add].
If it doesn't work
The above method may not work well in environments where git is not installed.
Download the appropriate version of com.katuusagi.constexpressionforunity.tgz from Releases, and then [Package Manager > + > Add package from tarball...] Use [Package Manager > + > Add package from tarball...] to install the package.
If it still doesn't work
Download the appropriate version of Katuusagi.ConstExpressionForUnity.unitypackage from Releases and Import it into your project from [Assets > Import Package > Custom Package].
How to Use ConstExpression
Normal usage
Creating Assembly for ConstExpression
- in any folder in the Project Browser, select [right click > Create > Folder].
- Set a name for the folder (e.g. ConstExpressionEntry).
- select [right click > Create > Assembly Definition Reference] on the folder of 2.
- Set an asset name (e.g.
ConstExpressionEntry.asmref). - Click on the asset of 4. and set
ConstExpressionEntrytoAssembly Definitionin Inspector.
Implementing Computation Functions
Implement the script as follows under the folder of the assembly for ConstExpression.
using Katuusagi.ConstExpressionForUnity;
public static class MyConstExpression
{
[ConstExpression]
public static int Add(int l, int r)
{
return l + r;
}
}
Functions with the ConstExpression attribute are subject to compile-time constant computations.
Constraints on compile-time constant computations.
There are several restrictions to performing compile-time constant computations.
ConstExpression Attribute
Only functions with the ConstExpression attribute are subject to compile-time constant computations.
Static Function
The ConstExpression attribute can only be attached to static functions.
Arguments/Return Values
The ConstExpression attribute may only be attached to functions with the following argument/return types.
| string | char | sbyte | byte |
| short | ushort | int | uint |
| long | ulong | float | double |
| bool | enum | null | struct - No reference type instances as members |
| ReadOnlyArray<string> | ReadOnlyArray<char> | ReadOnlyArray<sbyte> | ReadOnlyArray<byte> |
| ReadOnlyArray<short> | ReadOnlyArray<ushort> | ReadOnlyArray<int> | ReadOnlyArray<uint> |
| ReadOnlyArray<long> | ReadOnlyArray<ulong> | ReadOnlyArray<float> | ReadOnlyArray<double> |
| ReadOnlyArray<bool> | ReadOnlyArray<enum> | ReadOnlyArray<null> | ReadOnlyArray<struct> - No reference type instances as members |
| ReadOnlyArray<ReadOnlyArray<...>> |
Also, to perform compile-time constant computations, the value assigned to the argument must be a constant.
Failure to assign a constant will result in a warning.
// OK
MyConstExpression.Add(100, 200);
// OK
const int l = 100;
const int r = 200;
MyConstExpression.Add(l, r);
// NG
int l = 100;
int r = 200;
MyConstExpression.Add(l, r);
// NG
readonly int l = 100;
readonly int r = 200;
MyConstExpression.Add(l, r);
Because struct and ReadOnlyArray cannot be literalized, the return value is held as a static readonly variable.
If passed as an argument, it must be taken from the return value of the ConstExpression method.
// OK
MyConstExpression.Add(MyConstExpression.MakeVector2(10, 20), MyConstExpression.MakeVector2(30, 40));
// NG
MyConstExpression.Add(new Vector2(10, 20), new Vector2(30, 40));
CalculationFailedWarning option
Setting the ConstExpression attribute to CalculationFailedWarning=false will prevent the warning from occurring when assigning a non-constant value to an argument.
[ConstExpression(CalculationFailedWarning = false)]
public static int Add(int l, int r)
{
return l + r;
}
// No warning occurs.
int l = 100;
int r = 200;
MyConstExpression.Add(l, r);
Disabling ConstExpression
You can disable ConstExpression with the following notation.
[assembly:IgnoreConstExpression]
This attribute can also be type or method specific.
How to Use StaticExpression
Normal usage
Creating Assembly for StaticExpression
Implement the script as follows.
using Katuusagi.ConstExpressionForUnity;
public static class MyStaticExpression
{
[StaticExpression]
public static int Add(int l, int r)
{
return l + r;
}
}
Functions with the StaticExpression attribute are subject to runtime constant pre-computations.
Constraints on runtime constant pre-computations.
There are several limitations to performing runtime constant pre-computations.
StaticExpression屿§
Only functions with the StaticExpression attribute are subject to runtime constant pre-computations
Static Function
The StaticExpression attribute can only be attached to static functions.
Arguments/Return Values
The StaticExpression attribute can only be attached to functions with the following argument/return types.
Unlike ConstExpression, reflection types can be used.
| string | char | sbyte | byte |
| short | ushort | int | uint |
| long | ulong | float | double |
| bool | enum | null | struct - No reference type instances as members |
| delegate - Only static public members |
AppDomain | Assembly | Type |
| MemberInfo | Type/TypeInfo | ConstructorInfo | FieldInfo |
| PropertyInfo | MethodInfo | MethodBase | EventInfo |
| ReadOnlyArray<string> | ReadOnlyArray<char> | ReadOnlyArray<sbyte> | ReadOnlyArray<byte> |
| ReadOnlyArray<short> | ReadOnlyArray<ushort> | ReadOnlyArray<int> | ReadOnlyArray<uint> |
| ReadOnlyArray<long> | ReadOnlyArray<ulong> | ReadOnlyArray<float> | ReadOnlyArray<double> |
| ReadOnlyArray<bool> | ReadOnlyArray<enum> | ReadOnlyArray<null> | ReadOnlyArray<struct> - No reference type instances as members |
| ReadOnlyArray<delegate> - Only static public members |
ReadOnlyArray<AppDomain> | ReadOnlyArray<Assembly> | ReadOnlyArray<Type> |
| ReadOnlyArray<MemberInfo> | ReadOnlyArray<TypeInfo> | ReadOnlyArray<ConstructorInfo> | ReadOnlyArray<FieldInfo> |
| ReadOnlyArray<PropertyInfo> | ReadOnlyArray<MethodInfo> | ReadOnlyArray<MethodBase> | ReadOnlyArray<EventInfo> |
| ReadOnlyArray<ReadOnlyArray<...>> |
Also, to perform runtime constant pre-computations, the value assigned to the argument must be a constant.
Failure to assign a constant will result in a warning.
// OK
MyStaticExpression.Add(100, 200);
// OK
const int l = 100;
const int r = 200;
MyStaticExpression.Add(l, r);
// NG
int l = 100;
int r = 200;
MyStaticExpression.Add(l, r);
// NG
readonly int l = 100;
readonly int r = 200;
MyStaticExpression.Add(l, r);
Type arguments can also be used, but the type must be unambiguous.
Setting a GenericParameter to a type argument will result in a warning.
// OK
MyStaticExpression.Add<int>(100, 200);
// NG
MyStaticExpression.Add<T>(100, 200);
Because struct and ReadOnlyArray cannot be literalized, the return value is held as a static readonly variable. If passed as an argument, it must be taken from the return value of ConstExpression or StaticExpression.
// OK
MyStaticExpression.Add(MyStaticExpression.MakeVector2(10, 20), MyStaticExpression.MakeVector2(30, 40));
// NG
MyStaticExpression.Add(new Vector2(10, 20), new Vector2(30, 40));
CalculationFailedWarning option
Setting the ConstExpression attribute to CalculationFailedWarning=false will prevent the warning from occurring when assigning a non-constant value to an argument.
[StaticExpression(CalculationFailedWarning = false)]
public static int Add(int l, int r)
{
return l + r;
}
// No warning occurs.
MyStaticExpression.Add(l, r);
Disabling StaticExpression
You can disable StaticExpression with the following notation.
[assembly:IgnoreStaticExpression]
This attribute can also be type or method specific.
About ReadOnlyArray
ReadOnlyArray is an immutable array prepared as a return constant for ConstExpression.
It inherits from IReadOnlyList and can be implicitly cast to ReadOnlySpan.
Implicit casts from arrays are also possible.
// OK
ReadOnlyArray<byte> binary = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF };
// OK
ReadOnlySpan<byte> spanBinary = binary;
// OK
IReadOnlyList<byte> listBinary = binary;
// NG
byte[] bytes = binary;
No comments yet. Be the first!