Krotox Engine › Docs › Scripting API › Systems & Utilities
Time and time scale, pausing, the Mathf helpers, Vector2/Vector3/Vector4 and Quaternion, angle units, logging to the Console, drawing debug lines, boxes, circles and text, assertions, and profiler samples.
float dt = Time.DeltaTime; // scaled seconds this frame (same as OnUpdate's ts)
float rawDt = Time.UnscaledDeltaTime; // real seconds, ignores TimeScale
float fixedDt = Time.FixedDeltaTime; // the physics step (1/60 s by default)
float t = Time.ElapsedTime; // scaled seconds since Play
float rawT = Time.UnscaledElapsedTime;
ulong frame = Time.FrameCount;
Time.TimeScale = 0.5f; // slow motion; 0 freezes gameplay while the UI keeps working
Time.TimeScale resets to 1 when Play stops.
Frame-rate independence. Multiply anything that changes per frame by ts (or Time.DeltaTime) so it moves at the same speed at 30, 60 or 120 frames per second:
void OnUpdate(float ts)
{
Translation += new Vector3(Speed * ts, 0, 0); // units per second, at any frame rate
}
Pausing. Game.Pause(), Game.Resume() and Game.IsPaused pause gameplay while the UI stays live. Use unscaled time (WaitForSecondsRealtime, unscaled: true on tweens) for anything that must keep moving on a pause menu.
IEnumerator HitStop(float seconds)
{
Time.TimeScale = 0.0f;
yield return new WaitForSecondsRealtime(seconds);
Time.TimeScale = 1.0f;
}
// Constants
Mathf.PI; Mathf.Deg2Rad; Mathf.Rad2Deg; Mathf.Epsilon; Mathf.Infinity;
float c = Mathf.Clamp(value, 0.0f, 100.0f);
float c1 = Mathf.Clamp01(value);
float l = Mathf.Lerp(a, b, t); // t clamped to 0..1
float lu = Mathf.LerpUnclamped(a, b, t);
float la = Mathf.LerpAngle(a, b, t); // takes the short way around
float it = Mathf.InverseLerp(a, b, value); // the t that gives value
float s = Mathf.SmoothStep(from, to, t); // eased in and out
float m = Mathf.MoveTowards(current, target, maxDelta);
float ma = Mathf.MoveTowardsAngle(current, target, maxDelta);
float d = Mathf.DeltaAngle(current, target); // shortest signed difference
float pp = Mathf.PingPong(time, length); // 0 -> length -> 0
float r = Mathf.Repeat(time, length); // wraps, always positive
bool eq = Mathf.Approximately(a, b);
// Plus Sin, Cos, Tan, Asin, Acos, Atan, Atan2, Sqrt, Abs, Round, Floor, Ceil, Sign, Pow, Log, Log10
// Exponential smoothing that behaves the same at any frame rate
float k = 1.0f - Mathf.Pow(0.001f, ts); // reaches ~99.9% in one second
m_Camera.Translation = Vector3.Lerp(m_Camera.Translation, m_Target.Translation, k);
Vector2, Vector3 and Vector4 are structs with public X, Y, Z, W fields.
Vector2 v = new Vector2(3, 4);
float len = v.Length(); // 5
Vector2 dir = v.Normalized; // unit-length copy
v.Normalize(); // in place
// Presets: Zero, One, Up, Down, Left, Right (Vector3 also has Forward and Back)
float dist = Vector2.Distance(a, b);
float dot = Vector2.Dot(a, b);
float cross = Vector2.Cross(a, b); // scalar perp-dot product
float angle = Vector2.Angle(from, to); // 0 to 180 degrees
float sAng = Vector2.SignedAngle(from, to); // -180 to 180, counter-clockwise positive
Vector2 r = Vector2.Reflect(direction, normal);
Vector2 p = Vector2.Perpendicular(direction); // rotated 90 degrees counter-clockwise
Vector2 lp = Vector2.Lerp(a, b, t);
Vector2 mt = Vector2.MoveTowards(current, target, maxDistanceDelta);
Vector3 adds Cross (a vector), Project, ProjectOnPlane and SignedAngle(from, to, axis). Vector4 is also used for colours (red, green, blue, alpha).
Vector3 toTarget = target.WorldPosition - WorldPosition;
float angle = Mathf.Atan2(toTarget.Y, toTarget.X); // radians
Rotation = new Vector3(0, 0, angle);
Mostly for 3D, but handy for smooth rotation blends:
Quaternion q = Quaternion.Euler(0, 0, 90); // degrees
Quaternion mid = Quaternion.Slerp(a, b, t);
Vector3 euler = q.ToEulerAngles(); // degrees
Vector3 rotated = q * Vector3.Right;
Units.Entity.Rotation,Rigidbody2DComponent.RotationandUIRectComponent.Rotationare in radians.Quaternion.Euler,ToEulerAnglesandTween.RotateTouse degrees. Convert withMathf.Deg2RadandMathf.Rad2Deg.
There is no Color, Matrix4 or Random type in the engine API. Colours are Vector4; for random numbers use System.Random or KrotoxEngine.PCG.PCGSeededRandom.
Log.Trace("Very detailed");
Log.Info(quot;Position: {Translation}"); Log.Warn("Low health"); Log.Error("Missing reference");
Messages appear in the editor's Console with their severity, and in logcat on Android. Outside the engine (for example in a unit-test runner that loads your DLL), Log falls back to Console.WriteLine.
Draw shapes in the Viewport and the game view to see what your code is doing. Colours are Vector4. duration: 0 (the default) draws for one frame.
var red = new Vector4(1, 0, 0, 1);
var green = new Vector4(0, 1, 0, 1);
Debug.DrawLine(Vector3.Zero, Vector3.Up * 5.0f, red, duration: 1.0f);
Debug.DrawRay(WorldPosition, Vector3.Right, green);
Debug.DrawBox(center, new Vector2(2, 1), red); // 2D rectangle
Debug.DrawCircle(center, 1.5f, green, duration: 2.0f);
Debug.DrawText(WorldPosition + Vector3.Up, quot;HP {m_Health}", new Vector4(1, 1, 1, 1), size: 0.4f);
Debug.DrawTrajectoryArc(WorldPosition, launchVelocity, new Vector3(0, -9.8f, 0));
Vector2 origin = new Vector2(WorldPosition.X, WorldPosition.Y);
RaycastHit2D hit = Physics2D.Raycast(origin, Vector2.Down, 2.0f);
Vector3 end = hit.Hit ? new Vector3(hit.Point.X, hit.Point.Y, 0) : WorldPosition + Vector3.Down * 2.0f;
Debug.DrawLine(WorldPosition, end, hit.Hit ? new Vector4(0, 1, 0, 1) : new Vector4(1, 0, 0, 1));
Debug.Assert(m_Health >= 0, "Health went negative"); // logs an error with the call stack
Debug.Break(); // editor only: pauses the game here
Profiler.BeginSample("Pathfinding");
FindPath();
Profiler.EndSample();
Samples show up in profiling captures (and do nothing in other builds), next to the engine's own timings. The Profiler panel shows frame time and draw statistics live.