components/player__controller.cs

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.

NetworkingFile Access
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;
    }
}