terminalCode Example

Physics Tracing Code Examples

calendar_today May 3, 2026 schedule ~1 min read person patrickjr verified 50

Physics Tracing Code Examples

Raycast and shape trace examples using Scene.Trace — the builder pattern for physics queries.

CSHARP
// Physics Tracing Examples - Raycast and Shape Traces

using Sandbox;

public class PhysicsTracingExamples : Component
{
    // ==================== BASIC RAYCAST ====================
    
    void SimpleRaycast()
    {
        // Simple ray from start to end
        SceneTraceResult tr = Scene.Trace.Ray(startPos, endPos).Run();
        
        if (tr.Hit)
        {
            Log.Info($"Hit: {tr.GameObject} at {tr.EndPosition}");
            Log.Info($"Distance: {tr.Distance}");
            Log.Info($"Normal: {tr.Normal}");
            Log.Info($"Hitbox: {tr.Hitbox}"); // If UseHitboxes enabled
        }
    }
    
    // ==================== COLLISION RULES ====================
    
    void RaycastWithCollisionRules()
    {
        // Use project collision matrix (defined in project settings)
        var tr = Scene.Trace
            .Ray(eyePos, eyePos + forward * 1000)
            .WithCollisionRules("player", "weapon") // Use collision rules for these tags
            .Run();
    }
    
    void RaycastWithTagFiltering()
    {
        // Include only specific tags
        var tr = Scene.Trace
            .Ray(start, end)
            .WithTag("solid", "enemy")
            .Run();
            
        // Exclude specific tags
        var tr2 = Scene.Trace
            .Ray(start, end)
            .WithoutTag("trigger", "water")
            .Run();
    }
    
    // ==================== SHAPE TRACES ====================
    
    void SphereTrace()
    {
        // Sphere trace (swept sphere collision)
        var tr = Scene.Trace
            .Ray(start, end)
            .Size(radius) // Sphere radius
            .Run();
    }
    
    void BoxTrace()
    {
        // Box trace with custom size
        var tr = Scene.Trace
            .Ray(start, end)
            .Size(new BBox(-5, 5)) // Half-extents (10x10x10 box)
            .UseHitboxes(true) // Also hit player hitboxes
            .Run();
    }
    
    // ==================== ADVANCED TRACING ====================
    
    void MultiHitRaycast()
    {
        // Get all hits along the ray, not just first
        var results = Scene.Trace
            .Ray(start, end)
            .RunAll(); // Returns IEnumerable<SceneTraceResult>
            
        foreach (var hit in results)
        {
            Log.Info($"Hit: {hit.GameObject}");
        }
    }
    
    void IgnoreSelfRaycast()
    {
        // Ignore the GameObject this component is on
        var tr = Scene.Trace
            .Ray(gunPos, gunPos + direction * 10000)
            .IgnoreGameObject(GameObject)
            .Run();
    }
    
    // ==================== PRACTICAL EXAMPLES ====================
    
    void ShootWeapon()
    {
        // Weapon shooting with proper collision
        var tr = Scene.Trace
            .Ray(gun.WorldPosition, gun.WorldPosition + gun.WorldRotation.Forward * 10000)
            .WithoutTag("trigger") // Don't hit triggers
            .WithCollisionRules("weapon", "player") // Respect collision rules
            .UseHitboxes(true) // Hit player hitboxes for headshots
            .IgnoreGameObject(GameObject) // Don't hit yourself
            .Run();
            
        if (tr.Hit)
        {
            // Check for damageable component
            if (tr.GameObject.Components.TryGet<IDamageable>(out var damageable))
            {
                damageable.TakeDamage(Damage, tr.EndPosition, tr.Normal);
            }
            
            // Spawn impact effect
            if (tr.Surface != null)
            {
                tr.Surface.DoBulletImpact(tr);
            }
        }
    }
    
    void GroundCheck()
    {
        // Check if standing on ground
        var tr = Scene.Trace
            .Ray(WorldPosition, WorldPosition + Vector3.Down * 10)
            .WithTag("solid")
            .WithoutTag("player", "trigger")
            .Run();
            
        bool isGrounded = tr.Hit && tr.Distance < 0.1f;
    }
    
    void FindGroundAtPosition(Vector3 position)
    {
        // Find walkable ground below position
        var tr = Scene.Trace
            .Ray(position + Vector3.Up * 100, position + Vector3.Down * 1000)
            .WithTag("solid")
            .Run();
            
        if (tr.Hit)
        {
            Vector3 groundPosition = tr.EndPosition;
            Surface groundSurface = tr.Surface;
        }
    }
    
    void CheckLineOfSight(GameObject target)
    {
        // Check if target is visible (no walls in between)
        var tr = Scene.Trace
            .Ray(eyePos, target.WorldPosition)
            .WithTag("solid", "glass")
            .Run();
            
        bool hasLineOfSight = tr.Hit && tr.GameObject == target;
    }
}

TraceResult Properties

PropertyDescription
HitTrue if something was hit
GameObjectThe hit GameObject (null if no hit)
ComponentThe specific component hit (for shape traces)
EndPositionWorld position of hit
StartPositionWorld position trace started
DistanceDistance from start to hit
Fraction0-1 progress along trace (0=start, 1=end)
NormalSurface normal at hit point
DirectionNormalized trace direction
HitboxHitbox index if UseHitboxes was enabled
SurfaceSurface material properties
BodyPhysics body that was hit
TriangleMesh triangle index

Builder Pattern Methods

MethodPurpose
Ray(start, end)Define ray start and end
Size(radius)Sphere radius
Size(BBox)Box half-extents
WithTag(tags)Only hit objects with these tags
WithoutTag(tags)Ignore objects with these tags
WithCollisionRules(tag)Use collision matrix for tag
UseHitboxes(true)Include player hitboxes
UseRenderMeshes(true)Include render mesh collision
IgnoreGameObject(go)Skip specific GameObject
Run()Execute and return first hit
RunAll()Execute and return all hits
Was this helpful?