---
title: "Raycast a 2D physics world in C#"
url: https://recursiveai.org/onegame/cookbook/raycast-2d-physics-world/
description: "Find the nearest solid body along a line without moving it."
version: "2.0.0"
---

# Raycast a 2D physics world in C#

**onegame** is a free, open-source game engine for .NET from Recursive AI. MIT or Apache-2.0, no editor required.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneGame.Physics) · [GitHub](https://github.com/recursive-ai-oss/onegame) · [Docs](https://recursiveai.org/onegame/docs/) · [Download example (.zip)](https://recursiveai.org/onegame/cookbook/raycast-2d-physics-world/raycast-2d-physics-world.zip)

Find the nearest solid body along a line without moving it.

```shell
dotnet new console
dotnet add package RecursiveAI.OneGame.Physics
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

`Fixed` and `FVec2` are onegame’s deterministic fixed-point number and 2D vector types.

```csharp
using OneGame.Core;
using OneGame.Physics;

var space = new PhysicsSpace2D();
// size, center
space.AddBox(new FVec2(1, 2),
    new FVec2(3, 0));
if (space.Raycast(FVec2.Zero, new FVec2(1, 0),
    10, out var hit))
    Console.WriteLine(hit.Distance);
```

Casts right from the origin and prints `2.5`.

```text
2.5
```

Unzip [the example](https://recursiveai.org/onegame/cookbook/raycast-2d-physics-world/raycast-2d-physics-world.zip), then `dotnet run`.

## The full program

The full program identifies the static wall, prints the hit point, surface normal and distance, then casts upward to show a miss.

```csharp
using OneGame.Core;
using OneGame.Physics;

var space = new PhysicsSpace2D();
// size, center
var wall = space.AddBox(
    new FVec2(1, 2), new FVec2(3, 0),
    new BodyOptions { Kind = BodyKind.Static });
if (space.Raycast(FVec2.Zero, new FVec2(1, 0),
    10, out var hit))
{
    Console.WriteLine($"Hit wall: {hit.Body == wall}");
    Console.WriteLine($"Point: {hit.Point}");
    Console.WriteLine($"Normal: {hit.Normal}");
    Console.WriteLine($"Distance: {hit.Distance}");
}
var upwardHit = space.Raycast(
    FVec2.Zero, new FVec2(0, 1), 10, out _);
Console.WriteLine($"Upward hit: {upwardHit}");
```

`dotnet run` prints:

```text
Hit wall: True
Point: (2.5, 0)
Normal: (-1, 0)
Distance: 2.5
Upward hit: False
```

A zero direction or a nonpositive maximum distance throws `ArgumentOutOfRangeException`.

## Variations

### Filter the ray by layer

```csharp
using OneGame.Core;
using OneGame.Physics;

var space = new PhysicsSpace2D();
space.AddBox(new FVec2(1, 1), new FVec2(3, 0),
    new BodyOptions { Layer = 4 });
Console.WriteLine(space.Raycast(FVec2.Zero,
    new FVec2(1, 0), 10, out _, layers: 1u << 4));
```

```text
True
```

## Related recipes

- [2D platformer character controller in C#](https://recursiveai.org/onegame/cookbook/2d-character-controller/)
- [Filter 2D physics collision layers in C#](https://recursiveai.org/onegame/cookbook/filter-physics-collision-layers/)
- [Apply 2D forces and impulses in C#](https://recursiveai.org/onegame/cookbook/apply-2d-forces-and-impulses/)

## The short answer

Use `PhysicsSpace2D.Raycast(origin, direction, maxDistance, out hit)`. The return value tells you whether a solid body was found. On a hit, `RayHit` contains the body reference, world-space point, surface normal and distance from the origin. On a miss, the physics library sets the hit record to its default value, so branch on the Boolean before reading it.

The [raycast method](https://github.com/recursive-ai-oss/onegame/blob/60d5573da204de68cafd5896dc8d41b16c72ff9d/src/OneGame.Physics/PhysicsSpace2D.cs) finds the nearest body and skips triggers. It takes `Fixed` and `FVec2`, which lets simulation code query the same physics state that is stepped, saved and hashed with the game world.

## How do you use a raycast in 2D?

Choose the starting position, a nonzero direction and a positive reach. The direction can have any nonzero length: reach is supplied separately through `maxDistance`. The top snippet adds a box before querying it, so there is a real object to hit even though no simulation step has run yet.

The wall in the full program is centered at x = 3 and has width 1, so the rightward ray first reaches its left face at x = 2.5. That explains the printed distance and point. The normal points back toward the ray’s origin side, which in this case is left. Use the returned body reference to identify the thing hit rather than treating a nonzero distance as an identity check.

A ray is not a moving collider. Running a query does not apply an impulse, move a body or make a gameplay decision for you. If a hit should cause damage or activate an object, make that decision in simulation code and keep any resulting state on the appropriate entity. When querying in `OnTick`, remember the physics system runs after entity ticks: your query sees the state available before that upcoming step.

## Can raycasts hit triggers?

This 2D physics API skips triggers. Its public ray method has a layer-mask parameter, but no parameter that enables trigger hits. Setting a trigger’s layer bit in the mask does not override that behavior. For things entering and leaving a zone, use the space’s trigger events instead of expecting this ray query to report the zone.

The physics library’s normal is documented as zero if the ray begins inside a body. Do not normalize that result blindly or assume every hit normal is an outward direction suitable for a reflection. An inside-origin hit and an ordinary surface entry need different treatment if your game uses the normal to decide a response.

## How do you make a raycast ignore a layer?

Build the `layers` argument as a bit mask. The variation selects layer 4 with `1u << 4`, not the integer 4. Combine several allowed layer bits with OR, or leave unwanted bits unset. The default mask includes all layers. Query filtering is separate from the matrix that determines whether pairs of bodies collide.

If a ray misses unexpectedly, check the origin and direction in physics coordinates first. Simulation Y points up; screen pixels may point down. Then check reach, body layer and trigger status. The [debug overlay recipe](https://recursiveai.org/onegame/cookbook/draw-2d-physics-debug-overlay/) shows how to draw the actual collider outlines using a consistent world-to-screen transform.
