Add jumping and crouching, ensmoothen movement
This commit is contained in:
parent
d52cded64e
commit
60f59c1392
@ -18,3 +18,5 @@ MonoBehaviour:
|
|||||||
AirAcceleration: 15
|
AirAcceleration: 15
|
||||||
Friction: 20
|
Friction: 20
|
||||||
AirFriction: 15
|
AirFriction: 15
|
||||||
|
JumpVelocity: 5
|
||||||
|
LeanDegrees: 1
|
||||||
|
@ -18,3 +18,5 @@ MonoBehaviour:
|
|||||||
AirAcceleration: 5
|
AirAcceleration: 5
|
||||||
Friction: 8
|
Friction: 8
|
||||||
AirFriction: 4
|
AirFriction: 4
|
||||||
|
JumpVelocity: 8
|
||||||
|
LeanDegrees: 2
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -15,7 +15,7 @@ TagManager:
|
|||||||
-
|
-
|
||||||
- CollidableEnvironment
|
- CollidableEnvironment
|
||||||
- BulletHitLayer
|
- BulletHitLayer
|
||||||
-
|
- InvisibleToPlayerCamera
|
||||||
-
|
-
|
||||||
-
|
-
|
||||||
-
|
-
|
||||||
|
Loading…
Reference in New Issue
Block a user