|
using System.Collections; |
| using System.Collections.Generic; |
| using UnityEngine; |
|
|
| public class PlayerController : MonoBehaviour |
| { |
|
|
| [SerializeField] |
| private float movementSpeed; |
| [SerializeField] |
| private float groundCheckRadius; |
| [SerializeField] |
| private float jumpForce; |
| [SerializeField] |
| private float slopeCheckDistance; |
| [SerializeField] |
| private float maxSlopeAngle; |
| [SerializeField] |
| private Transform groundCheck; |
| [SerializeField] |
| private LayerMask whatIsGround; |
| [SerializeField] |
| private PhysicsMaterial2D noFriction; |
| [SerializeField] |
| private PhysicsMaterial2D fullFriction; |
|
|
| private float xInput; |
| private float slopeDownAngle; |
| private float slopeSideAngle; |
| private float lastSlopeAngle; |
|
|
| private int facingDirection = 1; |
|
|
| private bool isGrounded; |
| private bool isOnSlope; |
| private bool isJumping; |
| private bool canWalkOnSlope; |
| private bool canJump; |
|
|
| private Vector2 newVelocity; |
| private Vector2 newForce; |
| private Vector2 capsuleColliderSize; |
|
|
| private Vector2 slopeNormalPerp; |
|
|
| private Rigidbody2D rb; |
| private CapsuleCollider2D cc; |
|
|
| private void Start() |
| { |
| rb = GetComponent<Rigidbody2D>(); |
| cc = GetComponent<CapsuleCollider2D>(); |
|
|
| capsuleColliderSize = cc.size; |
| } |
|
|
| private void Update() |
| { |
| CheckInput(); |
| } |
|
|
| private void FixedUpdate() |
| { |
| CheckGround(); |
| SlopeCheck(); |
| ApplyMovement(); |
| } |
|
|
| private void CheckInput() |
| { |
| xInput = Input.GetAxisRaw("Horizontal"); |
|
|
| if (xInput == 1 && facingDirection == -1) |
| { |
| Flip(); |
| } |
| else if (xInput == -1 && facingDirection == 1) |
| { |
| Flip(); |
| } |
|
|
| if (Input.GetButtonDown("Jump")) |
| { |
| Jump(); |
| } |
|
|
| } |
| private void CheckGround() |
| { |
| isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround); |
|
|
| if(rb.velocity.y <= 0.0f) |
| { |
| isJumping = false; |
| } |
|
|
| if(isGrounded && !isJumping && slopeDownAngle <= maxSlopeAngle) |
| { |
| canJump = true; |
| } |
|
|
| } |
|
|
| private void SlopeCheck() |
| { |
| Vector2 checkPos = transform.position - (Vector3)(new Vector2(0.0f, capsuleColliderSize.y / 2)); |
|
|
| SlopeCheckHorizontal(checkPos); |
| SlopeCheckVertical(checkPos); |
| } |
|
|
| private void SlopeCheckHorizontal(Vector2 checkPos) |
| { |
| RaycastHit2D slopeHitFront = Physics2D.Raycast(checkPos, transform.right, slopeCheckDistance, whatIsGround); |
| RaycastHit2D slopeHitBack = Physics2D.Raycast(checkPos, -transform.right, slopeCheckDistance, whatIsGround); |
|
|
| if (slopeHitFront) |
| { |
| isOnSlope = true; |
|
|
| slopeSideAngle = Vector2.Angle(slopeHitFront.normal, Vector2.up); |
|
|
| } |
| else if (slopeHitBack) |
| { |
| isOnSlope = true; |
|
|
| slopeSideAngle = Vector2.Angle(slopeHitBack.normal, Vector2.up); |
| } |
| else |
| { |
| slopeSideAngle = 0.0f; |
| isOnSlope = false; |
| } |
|
|
| } |
|
|
| private void SlopeCheckVertical(Vector2 checkPos) |
| { |
| RaycastHit2D hit = Physics2D.Raycast(checkPos, Vector2.down, slopeCheckDistance, whatIsGround); |
|
|
| if (hit) |
| { |
|
|
| slopeNormalPerp = Vector2.Perpendicular(hit.normal).normalized; |
|
|
| slopeDownAngle = Vector2.Angle(hit.normal, Vector2.up); |
|
|
| if(slopeDownAngle != lastSlopeAngle) |
| { |
| isOnSlope = true; |
| } |
|
|
| lastSlopeAngle = slopeDownAngle; |
| |
| Debug.DrawRay(hit.point, slopeNormalPerp, Color.blue); |
| Debug.DrawRay(hit.point, hit.normal, Color.green); |
|
|
| } |
|
|
| if (slopeDownAngle > maxSlopeAngle || slopeSideAngle > maxSlopeAngle) |
| { |
| canWalkOnSlope = false; |
| } |
| else |
| { |
| canWalkOnSlope = true; |
| } |
|
|
| if (isOnSlope && canWalkOnSlope && xInput == 0.0f) |
| { |
| rb.sharedMaterial = fullFriction; |
| } |
| else |
| { |
| rb.sharedMaterial = noFriction; |
| } |
| } |
|
|
| private void Jump() |
| { |
| if (canJump) |
| { |
| canJump = false; |
| isJumping = true; |
| newVelocity.Set(0.0f, 0.0f); |
| rb.velocity = newVelocity; |
| newForce.Set(0.0f, jumpForce); |
| rb.AddForce(newForce, ForceMode2D.Impulse); |
| } |
| } |
|
|
| private void ApplyMovement() |
| { |
| if (isGrounded && !isOnSlope && !isJumping) //if not on slope |
| { |
| Debug.Log("This one"); |
| newVelocity.Set(movementSpeed * xInput, 0.0f); |
| rb.velocity = newVelocity; |
| } |
| else if (isGrounded && isOnSlope && canWalkOnSlope && !isJumping) //If on slope |
| { |
| newVelocity.Set(movementSpeed * slopeNormalPerp.x * -xInput, movementSpeed * slopeNormalPerp.y * -xInput); |
| rb.velocity = newVelocity; |
| } |
| else if (!isGrounded) //If in air |
| { |
| newVelocity.Set(movementSpeed * xInput, rb.velocity.y); |
| rb.velocity = newVelocity; |
| } |
|
|
| } |
|
|
| private void Flip() |
| { |
| facingDirection *= -1; |
| transform.Rotate(0.0f, 180.0f, 0.0f); |
| } |
|
|
| private void OnDrawGizmos() |
| { |
| Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius); |
| } |
|
|
| } |
|