unity2d 完美斜坡方案

核心代码
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 完美斜坡方案的更多相关文章
- JMessage是让App 同时集成 Push 功能与 IM 功能最完美的方案
历经几个月的沉寂,以及兄弟们的奋战,极光推送的兄弟产品诞生了:极光IM,英文名 JMessage. 极光IM 是我们团队基于大量客户的需求反馈,在很多客户的殷切期盼下所开发的.团队成员一方面要支撑极光 ...
- X86平台下嵌入式linux触摸屏解决方案(usb触摸屏控制器+完美校准方案+触摸屏QTE开发环境搭建)
一直在用X86平台,真心不想用WINCE和XPE,一些大的硬件供应商都不提供linux平台下的技术支持,比如研华的3343PC104系列的板子... 开发的问题如下: 1 USB控制器目前只有台湾和竹 ...
- Unity2D屏幕适配方案
看了cnblogs里的一篇文章,终于理解了Unity2D的摄像机系统:http://www.cnblogs.com/flyFreeZn/p/4073655.html 我根据他的方案,改写了两种适配方案 ...
- Microsoft.AspNet.Web.Optimization.Bundle的完美替换方案
Web应用程序中包含大量的样式(css)和脚本(js)文件,这些文件的引用.管理和发布有很多解决方案.在Asp.Net MVC应用程序中,大家最熟悉的解决方案应属Microsoft.AspNet.We ...
- C++类的完美单元测试方案——基于C++11扩展的friend语法
版权相关声明:本文所述方案来自于<深入理解C++11—C++11新特性解析与应用>(Michael Wong著,机械工业出版社,2016.4重印)一书的学习. 项目管理中,C语言工程做单元 ...
- Server-U FTP与AD完美集成方案详解
最近咱有个任务,那就是把公司的文件服务器.FTP服务器.邮件服务器进行迁移并作相应的整合.登陆后台查看了,公司目前正在使用的方案.FTP服务器使用的是Server-u FTP,验证方式选择的windo ...
- delphi之完美Splash方案(在TfrmMain.FormCreate里不断调用TfrmSplash显示加载进度文字,并且及时Update显示)
前言:网上有很多介绍delphi创建闪屏的代码,大多只是在程序开启前显示一个闪屏,但是却没有说如何在闪屏上显示程序加载的进度,于是笔者有意思介绍一下这种闪屏方式. 1.创建一个窗体(TfrmSplas ...
- 【jeecg-mybatis版本】 mybatis+spring mvc 完美整合方案 查询,保存,更新,删除自动生成
Jeecg-Mybatis版本代码生成器演示视频 http://pan.baidu.com/share/link?shareid=243717&uk=2668473880 简要说明 JE ...
- Linux终极shell-zsh的完美配置方案!——oh-my-zsh
Zsh 介绍 Zsh 兼容 Bash,据传说 99% 的 Bash 操作 和 Zsh 是相同的 Zsh 官网:http://www.zsh.org/ 先看下你的 Linux支持哪些 shell:cat ...
- ionic3-ng4学习见闻--(轮播图完美方案)
ionic上 轮播图是最坑的插件了吧,各种bug和 问题. 事件也不好用.. 于是,我终于搞出来了一个完美的方案, 适用于,动态获取轮播图数据,自动循环播放,跳转其他页面回来后自动播放,手指触摸后自动 ...
随机推荐
- 【笔记】用伽马函数证明标准正态分布EX4的值为3
2020-11-13 看了博客标准正态分布的E(X^4)积分求解的极坐标变换证明方法,已经叹服不已,然后看了底下老哥的评论,用伽马函数可以口算出来,遂去查了一下,真香!发篇博客记录一下. 现在的问题, ...
- Ant Design Pro版中后台原型模板及Axure rplib元件库组件
Ant Design Pro版中后台原型模板及Axure rplib元件库组件, Ant Design服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更 ...
- 天翼云出席DCIC2025,“翼立方”创新力拉满!
近日,由中国通信企业协会主办的DCIC2025(第14届)数据中心产业发展大会在北京召开.大会以"共筑算力基石,护航产业生态"为主题,邀请众多知名算力企业代表以及生态合作伙伴代表, ...
- vue3 基础-传送门 teleport
之前介绍了一波混入 mixin 和 自定义指令 directive 其基本作用就是为了在 vue 中实现代码的复用. 而本篇介绍的是 vue3 的一个新特性叫做传送门. 一听这个名字是不是就感觉特别科 ...
- 10个让你成为CSS画家的技巧,不容错过
@charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...
- Web前端入门第 54 问:JavaScript 3 种书写位置及 script 标签的正确存放位置
JS 的代码并没有强制规定放在 HTML 中的某个位置,如果您有使用过开发者工具查看过网页源码,那么您会看到很多 JS 代码都以 .js 文件的形式存放,并且放在了 HTML 文件最后,也就是 < ...
- MySQL order by if()或order by in()条件排序
需求背景 在做商品管理的时候,碰到一个SQL的排序问题,需要把上架的商品排在下架商品之前.一番折腾后,搜索到了条件排序语句 order by if(),小编在此和大家分享一下.本文测试数据存在如 ...
- 关于java中动态加载字节码的多种方法
关于java中动态加载字节码的多种方法 在反序列化漏洞中:经常会遇到TemplatesImpl或BCEL相关的代码,它们就是用来动态加载恶意字节码执行任意命令的; 以及理解这些机制也是理解内存马工作原 ...
- 玩转AI新声态 | 玩转TTS/ASR/YuanQI 打造自己的AI助手
前言 halo, 各位佬友这是我24年写的整理一下发出来, 可能有点老了, ai发展这么快...... 本次带来的是腾讯云玩转AI新声态语音产品应用实践,利用 TTS / ASR / 元器智能体 打造 ...
- MinHook 对.NET底层的 SendMessage 拦截真实案例反思
一:背景 1. 讲故事 上一篇我们说到了 minhook 的一个简单使用,这一篇给大家分享一个 minhook 在 dump 分析中的实战,先看下面的线程栈. 0:044> ~~[138c]s ...