using UnityEngine; using UnityEngine.InputSystem; namespace NeonTea.Quakeball.Player { /// A controller class for a local player. Handles input and updates the relevant components. [RequireComponent(typeof(Player))] public class LocalPlayer : MonoBehaviour { public Transform Camera; private float CameraPitch = 0; private Player Player; private InputAction LookAction; private InputAction MoveAction; private InputAction CrouchAction; private void Awake() { Player = GetComponent(); CrouchAction = new InputAction("crouch", binding: "/leftCtrl"); CrouchAction.Enable(); LookAction = new InputAction("look", binding: "/leftStick"); LookAction.AddBinding("/delta"); LookAction.Enable(); MoveAction = new InputAction("move", binding: "/rightStick"); MoveAction.AddCompositeBinding("Dpad") .With("Up", "/w") .With("Down", "/s") .With("Left", "/a") .With("Right", "/d"); MoveAction.Enable(); Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } private void Update() { OptionsData Opts = Options.Get(); Vector2 LookInput = LookAction.ReadValue() * Opts.LookSensitivity; Vector3 CamEulers = Camera.localEulerAngles; CamEulers.y += LookInput.x; CameraPitch = Mathf.Clamp(CameraPitch - LookInput.y * (Opts.InvertVerticalLook ? -1 : 1), -90, 90); CamEulers.x = CameraPitch; Camera.localEulerAngles = CamEulers; Player.HeadRotation = Camera.localRotation; } /// /// The player only moves on FixedUpdates, so movement-related inputs are handled here, so they get updated right before. /// (Script execution order should ensure that LocalPlayer is run before Player.) /// private void FixedUpdate() { Vector2 MovementInput = MoveAction.ReadValue(); Vector3 Move = new Vector3(MovementInput.x, 0, MovementInput.y); Vector3 Eulers = Player.HeadRotation.eulerAngles; Eulers.z = 0; Eulers.x = 0; Move = Quaternion.Euler(Eulers) * Move; Player.MoveDirection = Move; Player.MoveStyle = CrouchAction.ReadValue() ? Player.CrouchingMoveStyle : Player.RunningMoveStyle; } } }