S&box Wiki

Revision Difference

Traces#551506

<cat>Code.Game</cat>⤶ <cat>Code.Physics</cat>⤶ <title>Traces</title> # What are traces Traces are imaginary lines. When you run a Trace you get a TraceResult - which tells you what the line hit. So for example, if you, as the player, wanted to spawn a box. You'd run a Trace from the player's eyeball to 200 units in the direction that the player is looking. The TraceResult would show that it hit a point and now you know where to place the box. <upload src="a61e9/8d9152587ef3390.png" size="16905" name="image.png" /> # Tracing Traces are constructed using the [Trace](https://asset.party/api/Sandbox.Trace) static functions, and configured using member methods. You run the trace and get the result using [Run()](https://asset.party/api/Sandbox.Trace.Run()). ``` var mytrace = Trace.Ray( startPos, endPos ); mytrace = mytrace.WorldOnly(); var result = mytrace.Run(); ``` All configuration methods return a new `Trace` object. This is a convenience thing (known as [builder pattern](https://en.wikipedia.org/wiki/Builder_pattern)), so you can format traces like this: ``` var result = Trace.Ray( startPos, endPos ).WorldOnly().Run(); ``` or like this: ``` var result = Trace.Ray( startPos, endPos ) .Ignore( playerEntity ) .Ignore( playerVehicle ) .Size( 10 ) .Run(); ``` ## Size In the example above the `Size()` call describes the size of an AABB to trace. This means instead of tracing a simple line, you're tracing a bigger cube along the line. Please note that this cube would be axis aligned, meaning it cannot "rotate". ## RunAll Instead of ending your Trace with `Run()` function, you can use the [`RunAll()`](https://asset.party/api/Sandbox.Trace.RunAll()) function. Using `RunAll()` will tell your Trace that you don't want to stop at the first entity who's been hit. Instead it'll return an array containing a TraceResult for each entity that was hit along the path of the trace. An example use case for this function would be for bullets that penetrate through objects. ``` // Will return TraceResult[] that you can iterate over var tr = Trace.Ray( startPos, endPos ) .RunAll(); ``` # TraceResult The Trace Result is a simple structure. It gives you information such as whether and where the Trace hit, what it hit, etc. Here you can see testing whether the trace hit and using the hit position to spawn an entity 10 units above it. ``` if ( tr.Hit ) { var ent = new ModelEntity(); ent.SetModel( "models/sbox_props/watermelon/watermelon.vmdl" ); ent.Position = tr.EndPosition + tr.Normal * 10; } ``` # Box, Sphere, Capsule, PhysicsBody traces In addition to ray/line Traces, you can also trace with other shapes, using other static methods of the `Trace` class, for example an Axis-Aligned Bounding Box trace: ``` public void TraceVisualizer( Player owner, float maxDist ) { // This function should be called every frame (for example in a Sandbox weapon or a tool Simulate method) var startPos = owner.EyePosition; var dir = owner.EyeRotation.Forward; var box = new BBox( new Vector3( -30, -10, -30 ), new Vector3( 30, 0, 30 ) ); // Can also do Trace.Ray( .. ).Size( box ) var tr = Trace.Box( box, startPos, startPos + ( dir * maxDist ) ) .WithAllTags( "solid" ) .Ignore( owner ) .Run(); // Draw the line from start pos to hit pos DebugOverlay.Line( startPos, tr.HitPosition, Color.Yellow, 0f ); // Move the box to the start position, and adjust for weird shapes, and draw the starting position. var startBox = box.Translate( startPos - box.Center ); DebugOverlay.Box( startBox, Color.Yellow, 0f ); // Move the box to the hit position, and adjust for weird shapes, and draw the final position. var finalBox = box.Translate( tr.HitPosition - box.Center ); DebugOverlay.Box( finalBox, Color.Yellow, 0f ); } ``` <upload src="70c/8db83dafb0eebfa.mp4" size="5893635" name="sbox-dev_fCRs4KZAQv.mp4" /> Note how the box shape does NOT rotate with the player's view. The hit position will always be in the center of a given shape. Other shapes, such as spheres and capsules, work in the exact same way. `Trace.Body` allows you to trace any `PhysicsBody`, and therefore any custom shape. It **DOES** preserve the body's rotation.