Recursive AI

Queries and layers

All onephysics recipes

Decide which bodies collide with layers in OnePhysics, then ask the world what is where: a raycast, an overlap test filtered to one layer, and a circle cast that skips chosen bodies.

C#
using RecursiveAI.OneMath;
using RecursiveAI.OnePhysics;
using RecursiveAI.OnePhysics.Physics2D;
 
const int Ground = 1, Player = 2, Enemy = 3;
var world = new PhysicsWorld2D();
var ground = world.AddBox(new Vector2F(20, 1), at: new Vector2D(0, -0.5), type: BodyType.Static);
var player = world.AddCircle(0.5f, at: new Vector2D(-2, 0.5));
var enemy = world.AddCircle(0.5f, at: new Vector2D(2, 0.5));
var crate = world.AddBox(new Vector2F(1, 1), at: new Vector2D(5, 0.5));
ground.Layer = Ground;
player.Layer = Player;
enemy.Layer = Enemy;
world.IgnoreLayerCollision(Player, Enemy);          // players and enemies pass through each other
Console.WriteLine($"player collides with ground: {world.GetLayerCollision(Player, Ground)}, with enemies: {world.GetLayerCollision(Player, Enemy)}");
 
world.Step(1f / 60);
 
// Raycast from above: the first shape the ray meets.
if (world.Raycast(new Vector2D(2, 5), new Vector2F(0, -1), out var down))
    Console.WriteLine($"ray down at x=2 hits {(down.Body == enemy ? "enemy" : "?")} at y={down.Point.Y:F3}, {down.Distance:F3} m");
 
// Overlap: what is near a point, enemies only.
var enemiesOnly = QueryFilter2D.OnLayer(Enemy);
QueryHit2D[] around = world.OverlapCircleAll(new Vector2D(1, 0.5), 1.5f, enemiesOnly);
Console.WriteLine($"enemies within 1.5 m of (1, 0.5): {around.Length}");
 
// A circle cast that ignores the player and the enemy: the first thing in the way is the crate.
var solidOnly = new QueryFilter2D { Predicate = s => s.Body != player && s.Body != enemy };
if (world.CircleCast(new Vector2D(-5, 0.5), 0.25f, new Vector2F(1, 0), out var hit, 100f, solidOnly))
    Console.WriteLine($"circle cast: {(hit.Body == crate ? "crate" : "?")} after {hit.Distance:F3} m, normal {hit.Normal}");
Text
player collides with ground: True, with enemies: False
ray down at x=2 hits enemy at y=1.000, 4.000 m
enemies within 1.5 m of (1, 0.5): 1
circle cast: crate after 9.250 m, normal (-1, -2.7258277E-05)

The pieces

  • Layers are numbers you assign with body.Layer. IgnoreLayerCollision(a, b) makes two layers pass through each other; GetLayerCollision reads the table. Group indexes, category and mask bits and a pair filter give finer rules; the first rule that answers decides.
  • Queries: Raycast, CircleCast and the other shape casts return the first hit, a QueryHit2D with Body, Shape, Point, Normal, Fraction and Distance. The …All overlap forms return every hit; their span overloads allocate nothing.
  • QueryFilter2D narrows a query: OnLayer(layer), or a Predicate on the shape.

The circle cast stops at 9.25 m: the crate’s face is at x = 4.5 and the circle’s radius is 0.25. Queries never change the world, so they don’t change its hash. PhysicsQuery2D runs batches of queries in parallel with results in input order. More in queries and layers.