Skip to content

Physics

namespace Griff.Runtime;
public sealed class Physics : IKeepsState

Simple, predictable 2D physics for jam games. Bodies move one axis at a time and are pushed out of solid colliders and solid tilemaps, which gives tight platformer and top-down movement without tunnelling at normal speeds. Boxes, circles and polygons collide with each other in any combination. A tilemap whose cells aren’t square makes walls of its own shape (see WallShapes): on an isometric map a body stands on the diamond under its collider and slides along the solid diamonds’ edges, and on a hex map its collider meets the solid hexagons’ six sides and slides along them. A body that Rotates is a rigid shape instead: it’s pushed apart from what it touches at the points where they touch, so it spins, tips over and falls flat, and its box or polygon turns with it; everything else meets it turned, walks up its slant, and knocks it about. It knows bodies, colliders, hinges, ropes and the tilemaps they meet, and nothing of what they are to the game: what it moves reports what it touched (Touches), knocked (Impacts) and shoved (Pushes), and the systems that own crates and players say how their bodies meet others (a crate gives way to what pushes it; a rope hangs in front of a player, to grab). The world belongs to the scene its game is playing: the game’s physics system owns it, steps it and starts it afresh for each scene, and its questions (Raycast, OverlapBox and the rest) are about that scene.

public Vector2 Gravity { get; set; }

World units per second squared. Negative Y is down.

public IReadOnlyList<BodyGroup> Groups { get; set; }

Bodies welded together (a contraption’s Welds), set by the game before each step: each group is one rigid body, worked out with the bodies that turn (it turns as one when all its members rotate, round where its weight balances), and its members don’t collide with each other. An anchored group (welded to something without a body, or with a frozen member) holds still.

public List<Impact> ImpactList { get; }

The same, as a list to go through without an enumerator.

public IReadOnlyList<Impact> Impacts { get; }

The hard knocks of the last step, in the order it found them (the same every time): each pair of things that ran into each other hard enough, both ways round (see Impact).

public EntityPairSet Pushes { get; }

What shoved what along in the last step, in the order it happened: each body that ran into one that gives way to it (a Pushable crate, as its system says) and moved it, then what it moved. Crates shoved on in turn are there too, with the crate that shoved them.

public Scene Scene { get; }

The scene the world is of: the one its game is playing.

public EntityPairSet TriggerPairs { get; }

Each trigger and the collider overlapping it, as of the last step, in the order they were found.

public static Box BoundsOf(BoxCollider collider)

World-space box of a collider, from its entity’s position and scale: for one that turns with its body, the box round it as it’s turned (see WorldShape).

public static Circle BoundsOf(CircleCollider collider)

World-space circle of a collider. The radius scales with the larger of the entity’s X and Y scale.

public static Box BoundsOf(Collider collider)

The world-space box around any kind of collider.

public static IEnumerable<Box> BoundsOf(Tilemap tilemap)

World-space boxes covering a tilemap’s colliding tiles, one per horizontal run. Like colliders that don’t turn, they follow the entity’s position and scale but ignore its rotation.

public bool IsOnSlope(Collider collider)

True if collider is standing on (or touching) a slope tile.

public bool IsOnSlope(Scene scene, Collider collider)

Like IsOnSlope, in a scene of its own.

public bool OnlyOneWayBelow(Body body)

True if what body stands on is only one-way platforms, so dropping through them would fall: for drop-through on down and Jump.

public bool OnlyOneWayBelow(Scene scene, Body body)

Like OnlyOneWayBelow, in a scene of its own.

public IEnumerable<Entity> OverlapBox(Vector2 center, Vector2 size, string? layers = null)

Entities whose colliders (or solid tiles) overlap the box centered on center.

public IEnumerable<Entity> OverlapBox(Scene scene, Vector2 center, Vector2 size, string? layers = null)

Like OverlapBox, in a scene of its own.

public IEnumerable<Entity> OverlapCircle(Vector2 center, float radius, string? layers = null)

Entities whose colliders (or solid tiles) overlap the circle, e.g. for an explosion’s reach.

public IEnumerable<Entity> OverlapCircle(Scene scene, Vector2 center, float radius, string? layers = null)

Like OverlapCircle, in a scene of its own.

public IEnumerable<Entity> OverlapPoint(Vector2 point, string? layers = null)

Entities whose colliders (or solid tiles) contain point. With layers (e.g. “Enemy, Crate”), only colliders and tiles on those layers count.

public IEnumerable<Entity> OverlapPoint(Scene scene, Vector2 point, string? layers = null)

Like OverlapPoint, in a scene of its own.

public RaycastHit? Raycast(Vector2 origin, Vector2 direction, float maxDistance = Infinityf, Entity? ignore = null, bool includeTriggers = false, string? layers = null)

The first solid collider or tile along a ray, or null if nothing is within maxDistance. Colliders the ray starts inside are skipped, as are ignore and its children (typically the entity casting the ray). Triggers are skipped unless includeTriggers is set. With layers (e.g. “Default, Player” for an enemy’s line of sight), only those layers are hit.

public RaycastHit? Raycast(Scene scene, Vector2 origin, Vector2 direction, float maxDistance = Infinityf, Entity? ignore = null, bool includeTriggers = false, string? layers = null)

Like Raycast, in a scene of its own.

public void Reset()

Forgets trigger overlaps and what bodies stood on, as the game’s physics system does when the scene changes.

public static IEnumerable<ValueTuple<Box, bool>> SlopeShapes(Tilemap tilemap)

World-space cells of a tilemap’s slope tiles and which way each rises (see SlopeUpTiles); each is solid below the line across it. Empty unless the map is Solid (and square).

public static IEnumerable<ValueTuple<Box, bool>> TileShapes(Tilemap tilemap)

Like BoundsOf, also saying which runs are one-way platforms. Empty unless the map is Solid and square (other shapes’ cells are walls of their own: see WallShapes); background tiles are left out.

public static IEnumerable<Vector2[]> WallShapes(Tilemap tilemap)

World-space outlines of the walls a tilemap’s solid cells make where they aren’t square (an isometric map’s diamonds, a hex map’s hexagons), one per run along a row: the four corners of a run of diamonds, round from its top, or the hexagons’ edges all the way round, clockwise from the top left corner. What bodies meet on such a map; empty unless it’s Solid and not square. Background, one-way, ladder and slope tiles are left out (see IsBlocked).

public static readonly Vector2 DefaultGravity

The Gravity a game starts with: 25 units per second squared, down.