diff --git a/Assets/ScriptableObjects/MoveStyles/Crouching.asset b/Assets/ScriptableObjects/MoveStyles/Crouching.asset index 2f7efda..8e371b9 100644 --- a/Assets/ScriptableObjects/MoveStyles/Crouching.asset +++ b/Assets/ScriptableObjects/MoveStyles/Crouching.asset @@ -18,3 +18,5 @@ MonoBehaviour: AirAcceleration: 15 Friction: 20 AirFriction: 15 + JumpVelocity: 5 + LeanDegrees: 1 diff --git a/Assets/ScriptableObjects/MoveStyles/Running.asset b/Assets/ScriptableObjects/MoveStyles/Running.asset index 6b50562..c3f79a2 100644 --- a/Assets/ScriptableObjects/MoveStyles/Running.asset +++ b/Assets/ScriptableObjects/MoveStyles/Running.asset @@ -18,3 +18,5 @@ MonoBehaviour: AirAcceleration: 5 Friction: 8 AirFriction: 4 + JumpVelocity: 8 + LeanDegrees: 2 diff --git a/Assets/Scripts/Player/LocalPlayer.cs b/Assets/Scripts/Player/LocalPlayer.cs index 0c8b69a..86f14d8 100644 --- a/Assets/Scripts/Player/LocalPlayer.cs +++ b/Assets/Scripts/Player/LocalPlayer.cs @@ -7,19 +7,25 @@ namespace NeonTea.Quakeball.Player { public class LocalPlayer : MonoBehaviour { public Transform Camera; - private float CameraPitch = 0; + private float Lean = 0; private Player Player; private InputAction LookAction; private InputAction MoveAction; private InputAction CrouchAction; + private InputAction JumpAction; private void Awake() { Player = GetComponent(); - CrouchAction = new InputAction("crouch", binding: "/leftCtrl"); + CrouchAction = new InputAction("crouch", binding: "/buttonEast"); + CrouchAction.AddBinding("/leftShift"); CrouchAction.Enable(); + JumpAction = new InputAction("crouch", binding: "/buttonSouth"); + JumpAction.AddBinding("/space"); + JumpAction.Enable(); + LookAction = new InputAction("look", binding: "/leftStick"); LookAction.AddBinding("/delta"); LookAction.Enable(); @@ -31,35 +37,29 @@ namespace NeonTea.Quakeball.Player { .With("Left", "/a") .With("Right", "/d"); MoveAction.Enable(); + } - Cursor.lockState = CursorLockMode.Locked; + private void Start() { Cursor.visible = false; + Cursor.lockState = CursorLockMode.Locked; } 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; + Move = Quaternion.Euler(0, Player.Yaw, 0) * Move; Player.MoveDirection = Move; - Player.MoveStyle = CrouchAction.ReadValue() ? Player.CrouchingMoveStyle : Player.RunningMoveStyle; + Player.MoveStyle = CrouchAction.ReadValue() > 0 ? Player.CrouchingMoveStyle : Player.RunningMoveStyle; + Player.Jumping = JumpAction.ReadValue() > 0; + + Vector2 LookInput = LookAction.ReadValue() * Opts.LookSensitivity; + Player.Pitch = Mathf.Clamp(Player.Pitch - LookInput.y * (Opts.InvertVerticalLook ? -1 : 1), -90, 90); + Player.Yaw += LookInput.x; + float TargetLean = -Vector3.Dot(Player.GroundVelocity / Player.MoveStyle.TargetVelocity, Camera.right) * Player.MoveStyle.LeanDegrees; + Lean = Mathf.Lerp(Lean, TargetLean, 10f * Time.deltaTime); + Camera.localEulerAngles = new Vector3(Player.Pitch, Player.Yaw, Lean); } } } diff --git a/Assets/Scripts/Player/MoveStyle.cs b/Assets/Scripts/Player/MoveStyle.cs index 731e625..488e894 100644 --- a/Assets/Scripts/Player/MoveStyle.cs +++ b/Assets/Scripts/Player/MoveStyle.cs @@ -16,5 +16,9 @@ namespace NeonTea.Quakeball.Player { public float Friction; /// The friction coefficient in air. Higher values mean faster slowdown, should be less than or equal to Acceleration. public float AirFriction; + /// The velocity that the player jumps in this style. + public float JumpVelocity; + /// Degrees that the player leans when moving sideways in this style. + public float LeanDegrees; } } diff --git a/Assets/Scripts/Player/Player.cs b/Assets/Scripts/Player/Player.cs index 7142999..cecc338 100644 --- a/Assets/Scripts/Player/Player.cs +++ b/Assets/Scripts/Player/Player.cs @@ -12,10 +12,15 @@ namespace NeonTea.Quakeball.Player { public MoveStyle RunningMoveStyle; public MoveStyle CrouchingMoveStyle; public Transform Head; + public Transform Body; - [Header("Player head status")] - /// The euler angle of the player's head. - public Quaternion HeadRotation; + [Header("Player rotation status")] + /// The pitch of the player's head. + public float Pitch; + /// The total yaw of the player. Head yaw is Yaw - BodyYaw. + public float Yaw; + /// The yaw of the player body. Calculated from MoveDirection. + public float BodyYaw; [Header("Player movement status")] /// The direction the player is going. @@ -65,12 +70,7 @@ namespace NeonTea.Quakeball.Player { } public bool IsGrounded() { - return Time.fixedTime - GroundedTime <= CoyoteTime; - } - - /// Sets Heading via euler angles. - public void SetRotation(float xAngle, float yAngle) { - MoveDirection = Quaternion.Euler(xAngle, yAngle, 0) * Vector3.forward; + return Time.time - GroundedTime <= CoyoteTime && Vector3.Dot(GravitationalVelocity, Vector3.down) >= 0; } private void Awake() { @@ -79,20 +79,30 @@ namespace NeonTea.Quakeball.Player { } private void Update() { - Head.localRotation = Quaternion.Lerp(Head.localRotation, HeadRotation, 10f * Time.deltaTime); + if (MoveDirection.magnitude > 0) { + BodyYaw = Vector3.SignedAngle(Vector3.forward, MoveDirection, Vector3.up); + } + Body.localRotation = Quaternion.Lerp(Body.localRotation, Quaternion.Euler(0, BodyYaw, 0), 20f * Time.deltaTime); + Head.localRotation = Quaternion.Lerp(Head.localRotation, Quaternion.Euler(Pitch, Yaw - BodyYaw, 0), 15f * Time.deltaTime); + UpdateMovement(); } - private void FixedUpdate() { + private void UpdateMovement() { bool Grounded = IsGrounded(); if (Grounded) { - GravitationalVelocity = Vector3.zero; + if (Vector3.Dot(Vector3.down, GravitationalVelocity) > 0) { + GravitationalVelocity = Vector3.zero; + } + if (Jumping) { + GravitationalVelocity = Vector3.up * MoveStyle.JumpVelocity; + } } else { - GravitationalVelocity += Physics.gravity * Time.fixedDeltaTime; + GravitationalVelocity += Physics.gravity * Time.deltaTime; } float FrictionVelocityFactor = Mathf.Max(GroundVelocity.magnitude, MoveStyle.StopVelocity); - float Deccel = FrictionVelocityFactor * Time.fixedDeltaTime; + float Deccel = FrictionVelocityFactor * Time.deltaTime; if (Grounded) { Deccel *= MoveStyle.Friction; } else { @@ -104,7 +114,7 @@ namespace NeonTea.Quakeball.Player { Vector3 GroundNormal = GroundCast(); Vector3 FixedHeading = Vector3.ProjectOnPlane(MoveDirection, GroundNormal).normalized; float CurrentSpeed = Vector3.Dot(GroundVelocity, FixedHeading); - float Acceleration = MoveStyle.TargetVelocity * Time.fixedDeltaTime; + float Acceleration = MoveStyle.TargetVelocity * Time.deltaTime; if (Grounded) { Acceleration *= MoveStyle.Acceleration; } else { @@ -113,9 +123,9 @@ namespace NeonTea.Quakeball.Player { Acceleration = Mathf.Min(Acceleration, MoveStyle.TargetVelocity - CurrentSpeed); GroundVelocity += FixedHeading * Acceleration; - CharacterController.Move((GroundVelocity + GravitationalVelocity) * Time.fixedDeltaTime); + CharacterController.Move((GroundVelocity + GravitationalVelocity) * Time.deltaTime); if (CharacterController.isGrounded) { - GroundedTime = Time.fixedTime; + GroundedTime = Time.time; } } } diff --git a/ProjectSettings/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset index cdc1f3e..a1242bf 100644 --- a/ProjectSettings/DynamicsManager.asset +++ b/ProjectSettings/DynamicsManager.asset @@ -3,10 +3,11 @@ --- !u!55 &1 PhysicsManager: m_ObjectHideFlags: 0 - serializedVersion: 11 - m_Gravity: {x: 0, y: -9.81, z: 0} + serializedVersion: 13 + m_Gravity: {x: 0, y: -20, z: 0} m_DefaultMaterial: {fileID: 0} m_BounceThreshold: 2 + m_DefaultMaxDepenetrationVelocity: 10 m_SleepThreshold: 0.005 m_DefaultContactOffset: 0.01 m_DefaultSolverIterations: 6 @@ -22,6 +23,7 @@ PhysicsManager: m_AutoSyncTransforms: 0 m_ReuseCollisionCallbacks: 1 m_ClothInterCollisionSettingsToggle: 0 + m_ClothGravity: {x: 0, y: -9.81, z: 0} m_ContactPairsMode: 0 m_BroadphaseType: 0 m_WorldBounds: @@ -31,4 +33,5 @@ PhysicsManager: m_FrictionType: 0 m_EnableEnhancedDeterminism: 0 m_EnableUnifiedHeightmaps: 1 - m_DefaultMaxAngluarSpeed: 7 + m_SolverType: 0 + m_DefaultMaxAngularSpeed: 7 diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index e1753c3..516f025 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -15,7 +15,7 @@ TagManager: - - CollidableEnvironment - BulletHitLayer - - + - InvisibleToPlayerCamera - - -