Player controller component for a game actor. Handles input-based movement, jumping, camera orbit/rotation, visibility of the model for local/remote proxies, and basic grounded/moving state detection using scene traces and a Rigidbody.
using Sandbox;
public class Player__Controller : Component
{
[Property] public Rigidbody RigidBody {get;set;}
[Property] public ModelRenderer Model_Renderer {get;set;}
GameObject c;
protected override void OnStart()
{if (IsProxy) return;
c = Scene.Camera.GameObject;}
float w;
float a;
float s;
float d;
float x;
float y;
float Speed;
[Property] public float Speed_Modifier {get;set;} = 1;
bool Jump_Request;
[Sync] public bool IsJumping {get;set;}
[Property] public float Jump_Power {get;set;} = 2400000;
[Property] public float Camera_Offset {get;set;} = 50;
[Property] public float Ray_Distance {get;set;} = 50;
[Sync] public bool IsMoving {get;set;}
public bool Disabled {get;set;}
protected override void OnUpdate()
{ Visibility(); if (IsProxy) return;
State(); if (new Game.Overlay().IsPauseMenuOpen) return;
Camera(); if (!Disabled) Control();
}
void Control()
{
w = Input.Down("w") ? 1 : 0;
a = Input.Down("a") ? -1 : 0;
s = Input.Down("s") ? -1 : 0;
d = Input.Down("d") ? 1 : 0;
Speed = Input.Down("shift") ? 16000 : 8000;
Speed *= Speed_Modifier; Jump_Request = Input.Down("space");
var Forward = new Vector3(c.WorldRotation.Forward.x, c.WorldRotation.Forward.y, 0).Normal;
var Right = new Vector3(c.WorldRotation.Right.x, c.WorldRotation.Right.y, 0).Normal;
var Direction = (w * Forward + s * Forward + a * Right + d * Right).Normal * Time.Delta * Speed;
RigidBody.Velocity = RigidBody.Velocity.WithX(Direction.x).WithY(Direction.y);
if (Jump_Request && !IsJumping)
RigidBody.ApplyImpulse(new Vector3(0, 0, Jump_Power));
}
void Camera()
{
var Delta = Input.MouseDelta * Time.Delta * Preferences.Sensitivity;
x += Delta.x;
y -= Delta.y;
y = y.Clamp(-89, 89);
c.WorldPosition = WorldPosition + new Vector3(0, 0, Camera_Offset);
c.WorldRotation = new Angles(-y, -x, 0);
if (!Disabled) WorldRotation = new Angles(WorldRotation.Pitch(), c.WorldRotation.Yaw(), WorldRotation.Roll());
c.GetComponent<CameraComponent>().FieldOfView = Preferences.FieldOfView;}
void Visibility()
{
if (!IsProxy) {Model_Renderer.RenderType = ModelRenderer.ShadowRenderType.ShadowsOnly;
return;} Model_Renderer.RenderType = ModelRenderer.ShadowRenderType.On;
}
void State()
{
SceneTraceResult Ray = Scene.Trace
.Ray(WorldPosition, WorldPosition + new Vector3(0, 0, -Ray_Distance))
.IgnoreGameObject(GameObject).Run();
IsJumping = (
!Ray.Hit || RigidBody.Velocity.z > 1
|| RigidBody.Velocity.z < -1);
IsMoving = new Vector2(RigidBody.Velocity.x, RigidBody.Velocity.y).LengthSquared > 512;
}
}