Add jumping and crouching, ensmoothen movement

This commit is contained in:
Jens Pitkänen 2020-08-02 04:45:54 +03:00
parent d52cded64e
commit 60f59c1392
7 changed files with 63 additions and 42 deletions

View File

@ -18,3 +18,5 @@ MonoBehaviour:
AirAcceleration: 15 AirAcceleration: 15
Friction: 20 Friction: 20
AirFriction: 15 AirFriction: 15
JumpVelocity: 5
LeanDegrees: 1

View File

@ -18,3 +18,5 @@ MonoBehaviour:
AirAcceleration: 5 AirAcceleration: 5
Friction: 8 Friction: 8
AirFriction: 4 AirFriction: 4
JumpVelocity: 8
LeanDegrees: 2

View File

@ -7,19 +7,25 @@ namespace NeonTea.Quakeball.Player {
public class LocalPlayer : MonoBehaviour { public class LocalPlayer : MonoBehaviour {
public Transform Camera; public Transform Camera;
private float CameraPitch = 0; private float Lean = 0;
private Player Player; private Player Player;
private InputAction LookAction; private InputAction LookAction;
private InputAction MoveAction; private InputAction MoveAction;
private InputAction CrouchAction; private InputAction CrouchAction;
private InputAction JumpAction;
private void Awake() { private void Awake() {
Player = GetComponent<Player>(); Player = GetComponent<Player>();
CrouchAction = new InputAction("crouch", binding: "<Gamepad>/leftCtrl"); CrouchAction = new InputAction("crouch", binding: "<Gamepad>/buttonEast");
CrouchAction.AddBinding("<Keyboard>/leftShift");
CrouchAction.Enable(); CrouchAction.Enable();
JumpAction = new InputAction("crouch", binding: "<Gamepad>/buttonSouth");
JumpAction.AddBinding("<Keyboard>/space");
JumpAction.Enable();
LookAction = new InputAction("look", binding: "<Gamepad>/leftStick"); LookAction = new InputAction("look", binding: "<Gamepad>/leftStick");
LookAction.AddBinding("<Mouse>/delta"); LookAction.AddBinding("<Mouse>/delta");
LookAction.Enable(); LookAction.Enable();
@ -31,35 +37,29 @@ namespace NeonTea.Quakeball.Player {
.With("Left", "<Keyboard>/a") .With("Left", "<Keyboard>/a")
.With("Right", "<Keyboard>/d"); .With("Right", "<Keyboard>/d");
MoveAction.Enable(); MoveAction.Enable();
}
Cursor.lockState = CursorLockMode.Locked; private void Start() {
Cursor.visible = false; Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
} }
private void Update() { private void Update() {
OptionsData Opts = Options.Get(); OptionsData Opts = Options.Get();
Vector2 LookInput = LookAction.ReadValue<Vector2>() * 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;
}
/// <remarks>
/// 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.)
/// </remarks>
private void FixedUpdate() {
Vector2 MovementInput = MoveAction.ReadValue<Vector2>(); Vector2 MovementInput = MoveAction.ReadValue<Vector2>();
Vector3 Move = new Vector3(MovementInput.x, 0, MovementInput.y); Vector3 Move = new Vector3(MovementInput.x, 0, MovementInput.y);
Vector3 Eulers = Player.HeadRotation.eulerAngles; Move = Quaternion.Euler(0, Player.Yaw, 0) * Move;
Eulers.z = 0;
Eulers.x = 0;
Move = Quaternion.Euler(Eulers) * Move;
Player.MoveDirection = Move; Player.MoveDirection = Move;
Player.MoveStyle = CrouchAction.ReadValue<bool>() ? Player.CrouchingMoveStyle : Player.RunningMoveStyle; Player.MoveStyle = CrouchAction.ReadValue<float>() > 0 ? Player.CrouchingMoveStyle : Player.RunningMoveStyle;
Player.Jumping = JumpAction.ReadValue<float>() > 0;
Vector2 LookInput = LookAction.ReadValue<Vector2>() * 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);
} }
} }
} }

View File

@ -16,5 +16,9 @@ namespace NeonTea.Quakeball.Player {
public float Friction; public float Friction;
/// <summary>The friction coefficient in air. Higher values mean faster slowdown, should be less than or equal to <c>Acceleration</c>.</summary> /// <summary>The friction coefficient in air. Higher values mean faster slowdown, should be less than or equal to <c>Acceleration</c>.</summary>
public float AirFriction; public float AirFriction;
/// <summary>The velocity that the player jumps in this style.</summary>
public float JumpVelocity;
/// <summary>Degrees that the player leans when moving sideways in this style.</summary>
public float LeanDegrees;
} }
} }

View File

@ -12,10 +12,15 @@ namespace NeonTea.Quakeball.Player {
public MoveStyle RunningMoveStyle; public MoveStyle RunningMoveStyle;
public MoveStyle CrouchingMoveStyle; public MoveStyle CrouchingMoveStyle;
public Transform Head; public Transform Head;
public Transform Body;
[Header("Player head status")] [Header("Player rotation status")]
/// <summary>The euler angle of the player's head.</summary> /// <summary>The pitch of the player's head.</summary>
public Quaternion HeadRotation; public float Pitch;
/// <summary>The total yaw of the player. Head yaw is Yaw - BodyYaw.</summary>
public float Yaw;
/// <summary>The yaw of the player body. Calculated from MoveDirection.</summary>
public float BodyYaw;
[Header("Player movement status")] [Header("Player movement status")]
/// <summary>The direction the player is going.</summary> /// <summary>The direction the player is going.</summary>
@ -65,12 +70,7 @@ namespace NeonTea.Quakeball.Player {
} }
public bool IsGrounded() { public bool IsGrounded() {
return Time.fixedTime - GroundedTime <= CoyoteTime; return Time.time - GroundedTime <= CoyoteTime && Vector3.Dot(GravitationalVelocity, Vector3.down) >= 0;
}
/// <summary>Sets <c>Heading</c> via euler angles.</summary>
public void SetRotation(float xAngle, float yAngle) {
MoveDirection = Quaternion.Euler(xAngle, yAngle, 0) * Vector3.forward;
} }
private void Awake() { private void Awake() {
@ -79,20 +79,30 @@ namespace NeonTea.Quakeball.Player {
} }
private void Update() { 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(); bool Grounded = IsGrounded();
if (Grounded) { if (Grounded) {
GravitationalVelocity = Vector3.zero; if (Vector3.Dot(Vector3.down, GravitationalVelocity) > 0) {
GravitationalVelocity = Vector3.zero;
}
if (Jumping) {
GravitationalVelocity = Vector3.up * MoveStyle.JumpVelocity;
}
} else { } else {
GravitationalVelocity += Physics.gravity * Time.fixedDeltaTime; GravitationalVelocity += Physics.gravity * Time.deltaTime;
} }
float FrictionVelocityFactor = Mathf.Max(GroundVelocity.magnitude, MoveStyle.StopVelocity); float FrictionVelocityFactor = Mathf.Max(GroundVelocity.magnitude, MoveStyle.StopVelocity);
float Deccel = FrictionVelocityFactor * Time.fixedDeltaTime; float Deccel = FrictionVelocityFactor * Time.deltaTime;
if (Grounded) { if (Grounded) {
Deccel *= MoveStyle.Friction; Deccel *= MoveStyle.Friction;
} else { } else {
@ -104,7 +114,7 @@ namespace NeonTea.Quakeball.Player {
Vector3 GroundNormal = GroundCast(); Vector3 GroundNormal = GroundCast();
Vector3 FixedHeading = Vector3.ProjectOnPlane(MoveDirection, GroundNormal).normalized; Vector3 FixedHeading = Vector3.ProjectOnPlane(MoveDirection, GroundNormal).normalized;
float CurrentSpeed = Vector3.Dot(GroundVelocity, FixedHeading); float CurrentSpeed = Vector3.Dot(GroundVelocity, FixedHeading);
float Acceleration = MoveStyle.TargetVelocity * Time.fixedDeltaTime; float Acceleration = MoveStyle.TargetVelocity * Time.deltaTime;
if (Grounded) { if (Grounded) {
Acceleration *= MoveStyle.Acceleration; Acceleration *= MoveStyle.Acceleration;
} else { } else {
@ -113,9 +123,9 @@ namespace NeonTea.Quakeball.Player {
Acceleration = Mathf.Min(Acceleration, MoveStyle.TargetVelocity - CurrentSpeed); Acceleration = Mathf.Min(Acceleration, MoveStyle.TargetVelocity - CurrentSpeed);
GroundVelocity += FixedHeading * Acceleration; GroundVelocity += FixedHeading * Acceleration;
CharacterController.Move((GroundVelocity + GravitationalVelocity) * Time.fixedDeltaTime); CharacterController.Move((GroundVelocity + GravitationalVelocity) * Time.deltaTime);
if (CharacterController.isGrounded) { if (CharacterController.isGrounded) {
GroundedTime = Time.fixedTime; GroundedTime = Time.time;
} }
} }
} }

View File

@ -3,10 +3,11 @@
--- !u!55 &1 --- !u!55 &1
PhysicsManager: PhysicsManager:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
serializedVersion: 11 serializedVersion: 13
m_Gravity: {x: 0, y: -9.81, z: 0} m_Gravity: {x: 0, y: -20, z: 0}
m_DefaultMaterial: {fileID: 0} m_DefaultMaterial: {fileID: 0}
m_BounceThreshold: 2 m_BounceThreshold: 2
m_DefaultMaxDepenetrationVelocity: 10
m_SleepThreshold: 0.005 m_SleepThreshold: 0.005
m_DefaultContactOffset: 0.01 m_DefaultContactOffset: 0.01
m_DefaultSolverIterations: 6 m_DefaultSolverIterations: 6
@ -22,6 +23,7 @@ PhysicsManager:
m_AutoSyncTransforms: 0 m_AutoSyncTransforms: 0
m_ReuseCollisionCallbacks: 1 m_ReuseCollisionCallbacks: 1
m_ClothInterCollisionSettingsToggle: 0 m_ClothInterCollisionSettingsToggle: 0
m_ClothGravity: {x: 0, y: -9.81, z: 0}
m_ContactPairsMode: 0 m_ContactPairsMode: 0
m_BroadphaseType: 0 m_BroadphaseType: 0
m_WorldBounds: m_WorldBounds:
@ -31,4 +33,5 @@ PhysicsManager:
m_FrictionType: 0 m_FrictionType: 0
m_EnableEnhancedDeterminism: 0 m_EnableEnhancedDeterminism: 0
m_EnableUnifiedHeightmaps: 1 m_EnableUnifiedHeightmaps: 1
m_DefaultMaxAngluarSpeed: 7 m_SolverType: 0
m_DefaultMaxAngularSpeed: 7

View File

@ -15,7 +15,7 @@ TagManager:
- -
- CollidableEnvironment - CollidableEnvironment
- BulletHitLayer - BulletHitLayer
- - InvisibleToPlayerCamera
- -
- -
- -