Orbital Camera Controller

Started by gasleet · 8 months ago · 2 replies · 229 views

edited 8 months ago#1
gasleet
Member
JoinedAug 2024 Posts78 Score6,923
Simple Camera Controller. Feel free to use, extend and share. ❤
Uses a CameraComponent and GameObject as Property. <- You could also get these in OnEnabled().
using Sandbox;
using System;

public sealed class OrbitalCameraController : Component
{
	[Property, Description("Camera to control")] CameraComponent MainCamera;
	[Property, Description("GameObject to follow")] GameObject Player;

	[Property, Description("Starting distance")] int DistanceToPlayer = 2000;
	[Property, Description( "Minimal distance to player" )] int MinDistanceToPlayer = 600;
	[Property, Description( "Maximal distance to player" )] int MaxDistanceToPlayer = 10000;
	[Property, Description("Units one step zooms")] int ZoomStrength = 200;

	float Pitch = 0;
	float Yaw = 0;

	protected override void OnUpdate()
	{
		// Capture mouse and add to pitch and yaw angles
		Angles mouseMove = Input.AnalogLook;
		Pitch = (Pitch + mouseMove.pitch).Clamp( -85, 85 ); // Up&Down clamped in degrees
		Yaw += mouseMove.yaw;
		Rotation rotation = Rotation.From( Pitch, Yaw, 0 );

		SceneTraceResult checkingSightline = Scene.Trace
			.Ray( MainCamera.WorldPosition, Player.WorldPosition )
			.Radius(1)
			.IgnoreGameObjectHierarchy(GameObject) // Ignores itself. Use tags depending on your setup
			.Run();
		// DebugOverlay.Trace( checkingSightline );

		if ( Input.MouseWheel.y < 0 ) { DistanceToPlayer = Math.Min( DistanceToPlayer + ZoomStrength, MaxDistanceToPlayer ); }
		if ( Input.MouseWheel.y > 0 ) { DistanceToPlayer = Math.Max(DistanceToPlayer - ZoomStrength, MinDistanceToPlayer); }

		if ( checkingSightline.Hit ) // If sightline is blocked change distance to be in front of hit collider
		{
			DistanceToPlayer = Math.Max( (int)(checkingSightline.HitPosition - Player.WorldPosition).Length, MinDistanceToPlayer );
		}

		// Apply Position and Rotation
		MainCamera.WorldPosition = Player.WorldPosition - rotation.Forward * DistanceToPlayer;
		MainCamera.WorldRotation = rotation;
		
	}
}

Not sure if this is the nicest way of doing this, but I'm happy with it. 🙂 Please report any bugs or give tips!
Remember to edit the Pitch.Clamp(-85, 85) for your usecase.
edited:
This is how it looks. Just orbits 🛸 and zooms 🔎 
#2
Braxen 🐟
Member
JoinedJun 2021 Posts189 Score190
something i've yet to figure out is how to have it lerp smoothly but still stay at a distance, without parenting the camera to a center pivot object and rotating that instead
#3
gasleet
Member
JoinedAug 2024 Posts78 Score6,923
I'm not exactly sure what you mean. The camera orbiting nothing?
people
Log in to reply
You can't reply if you're not logged in. That would be crazy.