Skip to content

Extensions

using Clockwork.Utilities;

Clockwork includes several extension classes that add useful methods to common numeric and vector types. These are small quality-of-life additions that come up all the time in game code.

Vector Extensions

Vector2 projected = velocity.Projected(wallNormal);
Vector2 snapped = position.Rounded();
Vector2 grid = position.Floored();
Vector2 normalized = direction.Normalized();

Component manipulation:

Vector2 grounded = velocity.SetY(0);
Vector2 flippedX = direction.NegateX();
Vector2 flippedY = direction.NegateY();

There's also a static method for averaging two vectors:

Vector2 midpoint = VectorExtensions.Averaged(positionA, positionB);

Float Extensions

int rounded = someFloat.Rounded();
int floored = someFloat.Floored();
int ceiled = someFloat.Ceiled();
float wrapped = angle.Wrapped(360f);

The Wrapped overload with an out parameter tells you how many times the value wrapped:

float wrapped = value.Wrapped(max, out float wraps);

Integer Extensions

int wrapped = index.Wrapped(arrayLength);
int wrapped = index.Wrapped(max, out int wraps);

Quaternion Extensions

For 3D rotation work, quaternion extensions provide directional vectors and rotation helpers:

Vector3 forward = rotation.GetForward();
Vector3 right = rotation.GetRight();
Vector3 up = rotation.GetUp();

And rotation methods:

Quaternion rotated = rotation.RotateWorldAxis(Vector3.UnitY, radians);
Quaternion rotated = rotation.RotateLocalAxis(localAxis, radians);
Quaternion fresh = QuaternionExtensions.CreateRotation(Vector3.UnitY, radians);

Collection Extensions

GetIndices returns a list of every valid index in a collection, which is handy for iterating or shuffling indices rather than items:

List<int> indices = myList.GetIndices(); // [0, 1, 2, ...]

Scope

Scope is a small helper for running paired enter/exit actions using a using block. The exit action runs automatically when the scope is disposed, even if you return or throw early:

using (new Scope(() => RenderTexture.BeginDrawing(target), RenderTexture.EndDrawing))
{
    // draw to the render texture here
}
// EndDrawing has now been called

This keeps "begin/end" style APIs balanced without having to remember the closing call.