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

unity2d 完美斜坡方案的更多相关文章

  1. JMessage是让App 同时集成 Push 功能与 IM 功能最完美的方案

    历经几个月的沉寂,以及兄弟们的奋战,极光推送的兄弟产品诞生了:极光IM,英文名 JMessage. 极光IM 是我们团队基于大量客户的需求反馈,在很多客户的殷切期盼下所开发的.团队成员一方面要支撑极光 ...

  2. X86平台下嵌入式linux触摸屏解决方案(usb触摸屏控制器+完美校准方案+触摸屏QTE开发环境搭建)

    一直在用X86平台,真心不想用WINCE和XPE,一些大的硬件供应商都不提供linux平台下的技术支持,比如研华的3343PC104系列的板子... 开发的问题如下: 1 USB控制器目前只有台湾和竹 ...

  3. Unity2D屏幕适配方案

    看了cnblogs里的一篇文章,终于理解了Unity2D的摄像机系统:http://www.cnblogs.com/flyFreeZn/p/4073655.html 我根据他的方案,改写了两种适配方案 ...

  4. Microsoft.AspNet.Web.Optimization.Bundle的完美替换方案

    Web应用程序中包含大量的样式(css)和脚本(js)文件,这些文件的引用.管理和发布有很多解决方案.在Asp.Net MVC应用程序中,大家最熟悉的解决方案应属Microsoft.AspNet.We ...

  5. C++类的完美单元测试方案——基于C++11扩展的friend语法

    版权相关声明:本文所述方案来自于<深入理解C++11—C++11新特性解析与应用>(Michael Wong著,机械工业出版社,2016.4重印)一书的学习. 项目管理中,C语言工程做单元 ...

  6. Server-U FTP与AD完美集成方案详解

    最近咱有个任务,那就是把公司的文件服务器.FTP服务器.邮件服务器进行迁移并作相应的整合.登陆后台查看了,公司目前正在使用的方案.FTP服务器使用的是Server-u FTP,验证方式选择的windo ...

  7. delphi之完美Splash方案(在TfrmMain.FormCreate里不断调用TfrmSplash显示加载进度文字,并且及时Update显示)

    前言:网上有很多介绍delphi创建闪屏的代码,大多只是在程序开启前显示一个闪屏,但是却没有说如何在闪屏上显示程序加载的进度,于是笔者有意思介绍一下这种闪屏方式. 1.创建一个窗体(TfrmSplas ...

  8. 【jeecg-mybatis版本】 mybatis+spring mvc 完美整合方案 查询,保存,更新,删除自动生成

    Jeecg-Mybatis版本代码生成器演示视频 http://pan.baidu.com/share/link?shareid=243717&uk=2668473880   简要说明  JE ...

  9. Linux终极shell-zsh的完美配置方案!——oh-my-zsh

    Zsh 介绍 Zsh 兼容 Bash,据传说 99% 的 Bash 操作 和 Zsh 是相同的 Zsh 官网:http://www.zsh.org/ 先看下你的 Linux支持哪些 shell:cat ...

  10. ionic3-ng4学习见闻--(轮播图完美方案)

    ionic上 轮播图是最坑的插件了吧,各种bug和 问题. 事件也不好用.. 于是,我终于搞出来了一个完美的方案, 适用于,动态获取轮播图数据,自动循环播放,跳转其他页面回来后自动播放,手指触摸后自动 ...

随机推荐

  1. k8s之serviceaccount,登录账号创建

    kubectl  --> 认证 --->授权 -->准入控制 认证:证书 身份识别 授权:rbac  权限检查 准入控制:  补充授权机制 多个插件实现 只在创建 删除 修改 或做代 ...

  2. golang 接口按需获取资源

    场景 爬虫业务场景,我们需要调用三方接口获取代理ip地址,每个ip地址可以使用的时间有限和价格的,本着不浪费资源,我们在这里做一层封装. 当有其他业务调用我们接口的时候,会拉起定时任务,这个定时任务的 ...

  3. TwoSum---LeetCode进阶路①

    LeetCode敲门题: 题目: Given an array of integers, return indices of the two numbers such that they add up ...

  4. 极简版闹钟(java)

    package javaBasic; import java.awt.Toolkit; import java.awt.event.*; import java.text.SimpleDateForm ...

  5. tkela二次开发之lay文件解析

    在tekla的一些配置文件中绝大都是本文格式存储的,如.dim:.ad:.vi;.tpl等文件:但是其中.lay文件却是一个例外:这个文件用txt开打时里面是会有乱码的. 我们知道这个文件是在软件的界 ...

  6. 【TrafficMonitor】无法显示13代intel的CPU温度

    原因分析 TrafficMonitor的温度检测是利用了第三方软件LibreHardwareMonitor,并且这个问题可能与CPU有关 按照作者的指示,我们下载并启动了最新的LibreHardwar ...

  7. 使用Plop.js高效生成模板文件

    前情 开发是个创造型的职业,也是枯燥的职业,因为开发绝大多数都是每天在业务的代码中无法自拨,说到开发工作,就永远都逃不开新建文件的步骤,特别现在组件化开发胜行,每天都是在新建新建组件的道路上一去不返, ...

  8. 处理日期和时间的chrono库

    C++11中提供了日期和时间相关的库chrono,通过chrono库可以很方便地处理日期和时间,为程序的开发提供了便利.chrono库主要包含三种类型的类:时间间隔duration.时钟clocks. ...

  9. 不写代码,让 AI 生成手机 APP!保姆级教程

    你现在看到的 APP,是我完全用 AI 生成的,一行代码都没写!怎么做到的呢? 大家好,我是程序员鱼皮.AI 发展很快,现在随随便便就能生成一个网站,但是怎么纯用 AI 开发能在手机上运行的 APP ...

  10. 基于袋鼠云实时开发平台开发 FlinkSQL 任务的实践探索

    随着业务的发展,实时场景在各个⾏业中变得越来越重要.⽆论是⾦融.电商还是物流,实时数据处理都成为了其中的关键环节.Flink 凭借其强⼤的流处理特性.窗⼝操作以及对各种数据源的⽀持,成为实时场景下的⾸ ...