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

  • 相关阅读:
    基于layui的简易后台管理系统,后期会更新
    java基础语法知识(笔记)——(一)基本变量类型,循环,日期类
    JavaWeb学习总结(笔记)——SSM spring.xml的基本配置
    JavaWeb学习总结(笔记)——SSM中Web.xml文件
    JavaWeb学习总结(笔记)——SSM关键类及其作用
    JavaWeb学习总结(笔记)——关于SSM CRUD上传功能的总结
    JavaWeb——MVC与三层结构
    jquery结合highcharts插件显示实时数据动态曲线图
    jquery结合Highcharts插件实现动态数据仪表盘图形化显示效果
    在IE6/7下表格td标签没有内容时不显示边框?
  • 原文地址:https://www.cnblogs.com/sanyejun/p/12577525.html
Copyright © 2011-2022 走看看