data/templates/PlayerController.cs
using Sandbox;

public sealed class PlayerController : Component
{
    [Property] public float WalkSpeed { get; set; } = 220f;
    [Property] public float RunSpeed { get; set; } = 320f;
    [Property] public float JumpForce { get; set; } = 350f;
    [Property] public GameObject Eye { get; set; }
    [Property] public CharacterController CharacterController { get; set; }

    [Sync] public Angles EyeAngles { get; set; }

    protected override void OnUpdate()
    {
        if ( IsProxy ) return;

        // Camera Look Rotation
        var look = Input.AnalogLook;
        var angles = EyeAngles;
        angles.pitch = MathX.Clamp( angles.pitch + look.pitch, -89f, 89f );
        angles.yaw -= look.yaw;
        EyeAngles = angles;

        if ( Eye.IsValid() )
        {
            Eye.WorldRotation = Rotation.From( EyeAngles );
        }
    }

    protected override void OnFixedUpdate()
    {
        if ( IsProxy ) return;

        var cc = CharacterController ?? Components.Get<CharacterController>();
        if ( !cc.IsValid() ) return;

        var isRunning = Input.Down( "run" );
        var speed = isRunning ? RunSpeed : WalkSpeed;

        var wishDir = Input.AnalogMove.Normal * Rotation.FromYaw( EyeAngles.yaw );
        var wishVelocity = wishDir * speed;

        if ( cc.IsOnGround )
        {
            cc.Accelerate( wishVelocity );
            cc.ApplyFriction( 4.0f );

            if ( Input.Pressed( "jump" ) )
            {
                cc.Punch( Vector3.Up * JumpForce );
            }
        }
        else
        {
            cc.Velocity += Scene.PhysicsWorld.Gravity * Time.Delta;
            cc.Accelerate( wishVelocity.ClampLength( speed * 0.2f ) );
        }

        cc.Move();
    }
}