zoukankan      html  css  js  c++  java
  • unity2d 完美斜坡方案

    来自油管大神: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<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);
        }
    
    }

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

  • 相关阅读:
    一个误解: 单个服务器程序可承受最大连接数“理论”上是“65535”
    Memcached 命令简介
    MySQL性能测试
    WCF 面向服务的SOAP消息
    WCF SOAP消息剖析
    深入探析 socket
    C#设计模式(适配器模式)
    LoadRunner中的异常处理
    反射调用性能比较(附源码)
    避免 TCP/IP 端口耗尽
  • 原文地址:https://www.cnblogs.com/sanyejun/p/12577525.html
Copyright © 2011-2022 走看看