ExampleComponents/CameraPhysicsDebug.cs
public sealed class CameraPhysicsDebug : Component, Component.ExecuteInEditor
{
[Property] public int MaxPoints { get; set; } = 10000;
[Property] public int TracesPerFrame { get; set; } = 500;
[Range( 0, 10 )]
[Property] public float NormalLength { get; set; } = 2;
[Property] public TraceTypes TraceType { get; set; } = TraceTypes.Ray;
[Property] public bool Hitboxes { get; set; } = false;
public record struct Hitpoint( Vector3 Position, Vector3 Normal, Color Tint );
public enum TraceTypes
{
Ray,
Box,
Sphere
}
List<Hitpoint> worldPoints = new();
protected override void OnUpdate()
{
var start = WorldPosition;
Gizmo.Draw.LineThickness = 2;
Gizmo.Draw.LineSphere( start, 2.0f );
Sandbox.Utility.Parallel.ForEach( Enumerable.Range( 0, TracesPerFrame ), i =>
{
SceneTraceResult t = default;
var end = start + WorldRotation.Forward * 1000 + Vector3.Random * 400;
if ( TraceType == TraceTypes.Ray )
{
t = Scene.Trace
.Ray( start, end )
.UseHitboxes( Hitboxes )
.Run();
}
else if ( TraceType == TraceTypes.Box )
{
t = Scene.Trace
.Ray( start, end )
.Size( new BBox( Vector3.One * -5, Vector3.One * 5 ) )
.UseHitboxes( Hitboxes )
.Run();
}
else if ( TraceType == TraceTypes.Sphere )
{
t = Scene.Trace
.Ray( start, end )
.Radius( 5 )
.UseHitboxes( Hitboxes )
.Run();
}
if ( t.Hit )
{
lock ( worldPoints )
{
Color tint = Color.White;
worldPoints.Add( new Hitpoint { Position = t.EndPosition, Normal = t.Normal, Tint = tint } );
}
}
} );
foreach ( var t in worldPoints )
{
Gizmo.Draw.Color = t.Tint * new Color( (t.Normal.x + 1) * 0.5f, (t.Normal.y + 1) * 0.5f, (t.Normal.z + 1) * 0.5f );
Gizmo.Draw.Line( t.Position, t.Position + t.Normal * NormalLength );
}
if ( worldPoints.Count > MaxPoints )
{
worldPoints.RemoveRange( 0, worldPoints.Count - MaxPoints );
}
}
}