88 lines
2.4 KiB
C#
88 lines
2.4 KiB
C#
#nullable enable
|
|
using JetBrains.Annotations;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
[RequireComponent(typeof(PlayerInput), typeof(Rigidbody2D))]
|
|
public class PlayerMovement : MonoBehaviour {
|
|
[SerializeField] PlayerStats playerStats;
|
|
Rigidbody2D rb;
|
|
|
|
PlayerInput playerInput;
|
|
Vector2 moveDirection;
|
|
BaseState currentState = new NormalMovementState();
|
|
|
|
void Awake() {
|
|
rb = GetComponent<Rigidbody2D>();
|
|
playerInput = GetComponent<PlayerInput>();
|
|
}
|
|
|
|
void FixedUpdate() {
|
|
if (currentState.FixedUpdateState(this) is {} newState)
|
|
SwitchState(newState);
|
|
}
|
|
|
|
public void OnMove(InputAction.CallbackContext ctx) {
|
|
moveDirection = ctx.ReadValue<Vector2>();
|
|
if (moveDirection.sqrMagnitude > 1.0f)
|
|
moveDirection.Normalize();
|
|
}
|
|
|
|
public void OnJump(InputAction.CallbackContext ctx) {
|
|
if (!ctx.ReadValueAsButton())
|
|
return;
|
|
|
|
SwitchState(new JumpingMovementState());
|
|
}
|
|
|
|
void SwitchState(BaseState newState) {
|
|
currentState.LeaveState(this);
|
|
currentState = newState;
|
|
newState.EnterState(this);
|
|
}
|
|
|
|
class BaseState {
|
|
//TODO If we never do anything before enter, replace with constructor?
|
|
public virtual void EnterState(PlayerMovement playerMovement) {}
|
|
|
|
public virtual void LeaveState(PlayerMovement playerMovement) {}
|
|
|
|
[CanBeNull]
|
|
public virtual BaseState UpdateState(PlayerMovement playerMovement) => null;
|
|
|
|
[CanBeNull]
|
|
public virtual BaseState FixedUpdateState(PlayerMovement playerMovement) => null;
|
|
}
|
|
|
|
class NormalMovementState : BaseState {
|
|
public override BaseState FixedUpdateState(PlayerMovement playerMovement) {
|
|
playerMovement.rb.velocity = (Vector3)playerMovement.moveDirection * playerMovement.playerStats.movementSpeed;
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
class JumpingMovementState : BaseState {
|
|
Vector3 startPosition;
|
|
float startTime;
|
|
|
|
public override void EnterState(PlayerMovement playerMovement) {
|
|
startPosition = playerMovement.transform.position;
|
|
startTime = Time.time;
|
|
}
|
|
|
|
public override BaseState FixedUpdateState(PlayerMovement playerMovement) {
|
|
float currentTime = Time.time - startTime;
|
|
if (currentTime >= playerMovement.playerStats.safeZoneJumpDuration)
|
|
return new NormalMovementState();
|
|
|
|
playerMovement.rb.MovePosition(Vector3.Lerp(
|
|
startPosition,
|
|
playerMovement.playerStats.safeZonePosition,
|
|
currentTime / playerMovement.playerStats.safeZoneJumpDuration
|
|
));
|
|
|
|
return null;
|
|
}
|
|
}
|
|
} |