来自油管大神:https://www.youtube.com/watch?v=QPiZSTEuZnw&lc=z22ehdxp5wmrg1jkvacdp431qmalafpquvm0apfrjrxw03c010c&feature=em-comments

 

核心代码

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();

cc = GetComponent();

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);

}

}

工程地址:https://drive.google.com/drive/folders/1qxFq3EBkU0JLu_iwXOtEc9-dW6_C1SpL

 

推荐链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。