using System; using Movement; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using PlayerInput = Input.PlayerInput; namespace Player { public class PlayerController : MonoBehaviour, IMovement, PlayerInput.IPlayerControlActions { private const float DefaultJumpForce = 26.0f; private const float DefaultMass = 80.0f; private const float MaxSpeed = 700.0f; private const float MaxAirSpeed = 500.0f; private const float GravityScale = 6.0f; private const float AccelerationScale = 40.0f; private const float DecelerationScale = 60.0f; private const float RespawnLimit = -60.0f; //Took from tutorial : https://www.youtube.com/watch?v=7KiK0Aqtmzc private const float FallMultiplier = 3.0f; private const float LowJumpMultiplier = 40.0f; //End of credits private PlayerInput _controls; private Rigidbody2D _playerRigidbody2D; private SpriteRenderer _playerSpriteRenderer; private CollisionChecker _playerGroundTrigger; private CollisionChecker _playerInteractableTrigger; private CollisionChecker _playerWallTriggerLeft; private CollisionChecker _playerWallTriggerRight; private Orientation _orientation; private bool _moveKeyPressed; private bool _jumpKeyPressed; private float _xAxisValue; private float _speed; private bool _isOnAir; private bool _canJump; private bool _afterMoving; private void Awake() { _playerRigidbody2D = GetComponent(); _playerSpriteRenderer = GetComponent(); _playerGroundTrigger = GameObject.Find("PlayerGroundTrigger").GetComponent(); _playerInteractableTrigger = GameObject.Find("PlayerInteractableTrigger").GetComponent(); _playerWallTriggerLeft = GameObject.Find("PlayerWallTriggerLeft").GetComponent(); _playerWallTriggerRight = GameObject.Find("PlayerWallTriggerRight").GetComponent(); } private void Start() { _playerRigidbody2D.mass = DefaultMass; _playerRigidbody2D.gravityScale = GravityScale; _orientation = gameObject.GetComponent().flipX switch { true => Orientation.Left, false => Orientation.Right }; _canJump = true; BaseSpeed = 0.0f; } private void OnEnable() { if (_controls == null) { _controls = new PlayerInput(); _controls.PlayerControl.SetCallbacks(this); } _controls.PlayerControl.Enable(); } private void OnDisable() { _controls.Disable(); } private void FixedUpdate() { //Took from tutorial : https://www.youtube.com/watch?v=7KiK0Aqtmzc switch (_playerRigidbody2D.velocity.y) { case < 0: _playerRigidbody2D.velocity += Vector2.up * (Physics2D.gravity.y * (FallMultiplier - 1) * Time.fixedDeltaTime); break; case > 0 when !_jumpKeyPressed: _playerRigidbody2D.velocity += Vector2.up * (Physics2D.gravity.y * (LowJumpMultiplier - 1) * Time.fixedDeltaTime); break; } //End of credits if (_moveKeyPressed) Move(_xAxisValue); else _playerRigidbody2D.velocity = new Vector2(0.0f, _playerRigidbody2D.velocity.y); if (_jumpKeyPressed && _playerGroundTrigger.IsCollided && _canJump) Jump(); if (_afterMoving) DecelerationAfterMoving(); } private void Update() { _isOnAir = !_playerGroundTrigger.IsCollided; RespawnCheck(); } private void RespawnCheck() { if (gameObject.transform.position.y < RespawnLimit) SceneManager.LoadScene(SceneManager.GetActiveScene().name); } // PAUSE METHODS public bool IsPaused { get; private set; } public void Pause() { IsPaused = true; _playerRigidbody2D.simulated = IsPaused; } public void Resume() { IsPaused = false; _playerRigidbody2D.simulated = IsPaused; } // MOVE METHODS public float BaseSpeed { get => _speed; set { switch (_isOnAir) { case false when value > MaxSpeed: _speed = MaxSpeed; break; case true when value > MaxAirSpeed: _speed = MaxAirSpeed; break; default: { if (value < 0) _speed = 0; else _speed = value; break; } } } } public void Move(float value) { switch (_xAxisValue) { case < 0: _playerSpriteRenderer.flipX = true; _orientation = Orientation.Left; //prevent player from sticking to wall while moving to its direction in the air if (!_playerGroundTrigger.IsCollided && _playerWallTriggerLeft.IsCollided) return; break; case > 0: _playerSpriteRenderer.flipX = false; _orientation = Orientation.Right; //prevent player from sticking to wall while moving to its direction in the air if (!_playerGroundTrigger.IsCollided && _playerWallTriggerRight.IsCollided) return; break; } BaseSpeed += AccelerationScale; _playerRigidbody2D.velocity = new Vector2(BaseSpeed * _xAxisValue * Time.fixedDeltaTime, _playerRigidbody2D.velocity.y); } private void DecelerationAfterMoving() { BaseSpeed -= DecelerationScale; _playerRigidbody2D.velocity = new Vector2(BaseSpeed * (int)_orientation * Time.fixedDeltaTime, _playerRigidbody2D.velocity.y); if (BaseSpeed == 0) _afterMoving = false; } private void Jump() { BaseSpeed = MaxAirSpeed; _playerRigidbody2D.velocity = Vector2.up * DefaultJumpForce; _canJump = false; } private void Climb() { throw new NotImplementedException(); } // INPUT HANDLING public void OnMove(InputAction.CallbackContext context) { switch (context.canceled) { case true: _moveKeyPressed = false; _afterMoving = true; break; case false: _afterMoving = false; _moveKeyPressed = true; _xAxisValue = context.ReadValue(); break; } } public void OnJump(InputAction.CallbackContext context) { switch (context.canceled) { case true: _jumpKeyPressed = false; _canJump = true; break; case false: if (_playerGroundTrigger.IsCollided) _jumpKeyPressed = true; break; } } public void OnInteract(InputAction.CallbackContext context) { if (_playerInteractableTrigger.IsCollided) { } } public void OnClimb(InputAction.CallbackContext context) { Climb(); } private enum Orientation { Left = -1, Right = 1 } } }