---
title: "Raycasts and collision layers in C#"
url: https://recursiveai.org/onephysics/cookbook/queries-and-layers/
description: "Raycast in C# 2D physics: cast rays and circles, test overlaps, and use collision layers to choose what collides and what a query sees. Runnable code, with OnePhysics (preview)."
version: "0.4.0-preview.1"
---

# Raycasts and collision layers in C#

`world.Raycast(origin, direction, out hit)` returns the first shape a ray meets, with the point, normal and distance. Layers decide which bodies collide, and a `QueryFilter2D` decides what a query sees. The program below sets up a player, an enemy and a crate on three layers, then casts a ray, tests an overlap and sweeps a circle.

```shell
dotnet new console -o Raycast && cd Raycast
dotnet add package RecursiveAI.OnePhysics --version 0.4.0-preview.1
```

Put this in `Program.cs` and run `dotnet run`:

```csharp
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
bool withGround = world.GetLayerCollision(Player, Ground);
bool withEnemies = world.GetLayerCollision(Player, Enemy);
Console.WriteLine($"player collides with ground: {withGround}, "
    + $"with enemies: {withEnemies}");

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: it hits the crate.
var solidOnly = new QueryFilter2D
{
    Predicate = s => s.Body != player && s.Body != enemy,
};
var from = new Vector2D(-5, 0.5);
if (world.CircleCast(from, 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.

## Limits

- **OnePhysics is a preview** (0.4.0-preview.1, .NET 10) and is paused for now. The API and results may change between previews.
- **32 layers,** numbered 0 to 31. Group indexes, category and mask bits and the pair filter cover finer rules.
- **Coordinates within ±2^22 m** of the origin, finite; a ray’s direction must be nonzero, and it is normalized for you.

More in [queries and layers](https://recursiveai.org/onephysics/docs/queries-and-layers/).
