scripts/LidarControler.cs

Component that controls a Lidar scanner. On player Attack1 input it fires multiple scene raycasts from the current camera position and rotation (with optional random FOV jitter) and adds hit points to the referenced Lidar instance.

NetworkingFile Access
using Sandbox;
using Sandbox.Diagnostics;
using System;

public sealed class LidarControler : Component
{
	[Property] public Lidar lidar;
	[Property] public float randomFov = 0f;
	[Property] public float fireRate = 1 / 30f;
	[Property] public int rayBachCount = 5;

	public float lastFire = 0f;
	private CameraComponent camera;
	private Random random;

	protected override void OnUpdate()
	{
		if ( Input.Down( "Attack1" ) )
		{
			BasicRay();
		}

		base.OnUpdate();
	}

	protected override void OnStart()
	{
		camera = Scene.Camera;
		random = new();

		base.OnStart();
	}

	private Rotation randomRotionFov( float randomFov )
	{
		float angle = random.Float( 0f, MathF.PI * 2f );
		float radius = MathF.Sqrt( random.Float( 0f, 1f ) ) * randomFov;

		float x = MathF.Cos( angle ) * radius;
		float y = MathF.Sin( angle ) * radius;

		return Rotation.From( x, y, 0f );
	}

	private void FireRay( Vector3 pos, Rotation rot )
	{
		SceneTraceResult tr = Scene.Trace
			.Ray( pos, pos + rot.Forward * 1e6f )
			.WithoutTags( "lidar" )
			.Run();

		if ( tr.Hit == false ) { return; }

		lidar.AddPoint(
			tr.HitPosition - tr.Normal * 0.01f,
			tr.Normal
		);
	}


	private void BasicRay()
	{
		float nowTime = Time.Now;
		if ( (nowTime - lastFire) < fireRate )
		{
			return;
		}

		Vector3 pos = camera.WorldPosition;
		Rotation rot = camera.WorldRotation;

		for ( var i = 0; i < rayBachCount; i++ )
		{
			FireRay( pos, rot * randomRotionFov( randomFov ) );
		}

		lastFire = nowTime;
	}
}