Unity 个人用过的地面检测方案总结
1.普通射线
在角色坐标(一般是脚底),发射一根向下的射线(长度约0.2)
但是简单射线只适用于简单地形,实际使用中常常遇到以下问题
- 用collider去碰撞地面,某些时候会有一定的穿插,于是角色的最低点就可能穿透地面,你发射射线的点可能就到了地面以下,射线一直检测不到真正的地面,于是角色就一直悬空
- 角色走斜坡时,角色中点可能会离开地面一小段距离,这一小段距离往往就足够让判断机制误以为角色已经离地,如果你增加射线的长度,那么一定程度上能缓解斜坡问题,但是会降低跳跃判断的精度,精度过低就有可能出现:角色跳起,会有那么一小段距离,其实已经离地了,但是仍然返回了isGround = true;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RaycastTest : MonoBehaviour {
private bool isGround = false;
private Rigidbody2D myRigidbody2D;
void Awake () {
myAnimator = GetComponent<Animator>();
myRigidbody2D = GetComponent<Rigidbody2D>();
}
void FixedUpdate () {
Debug.DrawRay(transform.position, Vector2.down * 0.11f, Color.red);
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 0.15f, 1 << 8);
if (hit.collider != null)
isGround = true;
else
isGround = false;
}
2.Unity官方的Character Controller
直接给角色加入Character Controller组件,在脚本中Get到Character Controller,调用.isGrounded即可,但是实际效果让人失望
因为.isGrounded是当角色移动的时候才会检测是否着地的,也就是说它只能在调用simplemove(和move等移动函数)时,判断isGrounded(是否着地)
这时播放一些动画会导致判断在true和false状态来回切换,并且Skinwidth也会导致这种问题,再加上一些角色控制器的限制,逻辑上不是那么自由,例如需要自己实现物理模拟,比如重力,个人觉得非常麻烦,不推荐
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OnGroundSensor : MonoBehaviour
{
public CapsuleCollider capcol;
public float offset = 0.1f;
private Vector3 point1;
private Vector3 point2;
private float radius;
void Awake()
{
radius = capcol.radius - 0.05f;
}
void FixedUpdate()
{
point1 = transform.position + transform.up * (radius - offset);
point2 = transform.position + transform.up * (capcol.height - offset) - transform.up * radius;
Collider[] outputCols = Physics.OverlapCapsule(point1, point2, radius, LayerMask.GetMask("Ground"));
if (outputCols.Length != 0)
{
//foreach (var col in outputCols)
// print("collision:" + col.name);
SendMessageUpwards("IsGround");
}
else
SendMessageUpwards("IsNotGround");
}
}
3.三射线
这个方法是社团内的Aery同志传授的,他应用到了一个2d卷轴游戏上https://github.com/KillerAery/DarkAdventrue
写法和简单射线没有什么不同,区别在于给角色加上三条射线:左脚,右脚,裆
三条射线有一条返回true则isGround为true
在我们的这个2d游戏上表现不错
我们看看他的代码
float dt = Time.deltaTime;
//累计时间
vida.chargeTimer += dt;
vida.jumpTimer += dt;
//TODO 待优化代码
//是否到地面 用三个groundCheck来检测
//public Transform[] groundChecks = new Transform[3];
for (int i = 0; i < 3; ++i)
{
checkResult = Physics2D.Linecast(transform.position,
groundChecks[i].position,
1 << LayerMask.NameToLayer("Ground"));
vida.grounded = checkResult;
if (vida.grounded) break;
}
if (vida.grounded)
{
//火箭蛋(硬件蛋特殊技能)
if (vida.playerType == Tags.YingjianDan)
{
vida.jumpable = 1;
}
}
//跳跃
//按下K时
if (Input.GetKeyDown(KeyCode.K) && vida.jumpTimer >= 0.03f)
{
if (vida.grounded)
{
//允许跳跃
vida.jumpTimer = 0.0f;
vida.jump = true;
}
else if (vida.jumpable > 0)
{
vida.jumpable--;
//允许跳跃
vida.jumpTimer = 0.0f;
vida.jump = true;
}
}
4.OverlapCapsule 投射胶囊碰撞体
这个方法是看傅老师的黑魂复刻系列视频学的


point0,point1,radius 分别为胶囊体起点球心,胶囊体终点球心,胶囊体半径
我们这里只要用到这一重载方法 Physics.OverlapCapsule(pointBottom, pointTop, radius, LayerMask)
private CapsuleCollider capsuleCollider;
private Vector3 pointBottom, pointTop;
private float radius;
void Awake () {
capsuleCollider = GetComponent<CapsuleCollider>();
radius = capsuleCollider.radius;
}
LayerMask设置方法:
最后提下这个LayerMask
假设ground层为10,指定碰撞第10层Layer,写法为:Layermask mask=1<<10
但是,投射的胶囊体也会检测自己本身,如果你希望游戏中基本上任何能碰撞物体都能够用来站脚,那么应设置为:碰撞除了角色所在的Layer以外的所有层(假设Player层为8
写法为:~(1<<8)
bool OnGround() {
pointBottom = transform.position + transform.up * radius-transform.up*overLapCapsuleOffset;
pointTop = transform.position + transform.up * capsuleCollider.height - transform.up * radius;
LayerMask ignoreMask = ~(1 << 8);
colliders = Physics.OverlapCapsule(pointBottom, pointTop, radius, ignoreMask);
Debug.DrawLine(pointBottom, pointTop,Color.green);
if (colliders.Length!=0)
{
isOnGround = true;
return true;
}
else
{
isOnGround = false;
return false;
}
}
Unity 个人用过的地面检测方案总结的更多相关文章
- Linux入侵痕迹检测方案【华为云技术分享】
背景说明 扫描是一切入侵的基础,通过扫描来发现目标主机是否为活动主机.操作系统是什么版本.开放了哪些服务等.扫描技术纷繁复杂,新的扫描技术也层出不穷,不可能穷举所有扫描技术,下面按入侵步骤对主机扫描. ...
- LCD显示器缺陷自动化检测方案
很牛的测试 参考: 1.https://www.radiantvisionsystems.com/ 2.https://www.radiantvisionsystems.com/node/275 LC ...
- Unity正交相机智能包围物体(组)方案
Unity正交相机智能包围物体(组)方案 目录 Unity正交相机智能包围物体(组)方案 一.技术背景 二.相关概念 2.1 正交摄像机 2.2 正交相机的Size 2.3 相机的Aspect 2.4 ...
- 【Unity入门】碰撞检测与触发检测
版权声明:本文为博主原创文章,转载请注明出处. 在Unity里面,游戏物体的碰撞我们可以通过刚体组件(Rigidbody)和碰撞器组件(Collider)来进行检测.首先在场景里面添加一个Plane面 ...
- Nginx主动检测方案---Tengine
方案选择大致如下: 1.用Tengine来代替Nginx, http://tengine.taobao.org/ Tengine是由淘宝网发起的Web服务器项目.它在Nginx的基础上,针对大访问 ...
- 一次误报引发的DNS检测方案的思考:DNS隧道检测平民解决方案
摘自:http://www.freebuf.com/articles/network/149328.html 通过以上分析得出监控需要关注的几个要素:长域名.频率.txt类型.终端是否对解析ip发起访 ...
- 日常小节----unity小坑记(射线检测固定层级)
unity中射线检测需设定所需层级时,必须加上距离!!! //一条从主相机到屏幕点击点的射线 Ray ray = Camera.Main.ScreenPointToRay(Input.mousePos ...
- Unity的学习笔记(射线检测)
首先,射线检测的API是这样的,网上找了一下,这个图片看得很清楚: 接下来是自己使用这个进行测试 using System.Collections; using System.Collections. ...
- 冰蝎动态二进制加密WebShell基于流量侧检测方案
概述 冰蝎是一款新型动态二进制加密网站工具.目前已经有6个版本.对于webshell的网络流量侧检测,主要有三个思路.一:webshell上传过程中文件还原进行样本分析,检测静态文件是否报毒.二:we ...
随机推荐
- JDK安装路径下的JRE与独立安装的JRE区别
在JDK安装目录下的子文件下,已经默认安装了一个jre.且与独立安装的JRE6所包含的文件几乎完全一样. JDK里面内置的JRE和独立的JRE是有一点差别的: 在JDK安装文件中包含了一个完整的独立版 ...
- Spring中加载xml配置文件的常用的几种方式
https://blog.csdn.net/qq877507054/article/details/62432062
- Python002-操作MSSQL(Microsoft sql server)基础示例(二)
前文http://www.cnblogs.com/fengpingfan/p/7675291.html,讲述了python操作mssql的步骤.环境创建.常用方法等,本文将实例演示python操作ms ...
- 04.常量变量和数据类型(const)
1.关键字 2.数据类型 告诉编译器定义一个类型变量的空间! 3.常量 4.变量 在程序运行过程中,值可以改变 变量在使用前必须先定义,定义变量前必须有相应的数据类型 标识符命名规则: (1).标识符 ...
- 于用cocoapods添加第三方库,并且cocoapods添加成功,但是却在任何一个文件上都导入不了头文件
关于用cocoapods添加第三方库,并且cocoapods添加成功,但是却在任何一个文件上都导入不了头文件,而且根本没有提示,即使手动打#import "xxxx.h"也报错xx ...
- 如何优雅的运行起jmeter
安装jdk 下载网站:http://www.oracle.com/,选个最新的版本就可以. 注意:11以后没有自动生成jre 配置环境变量 对于Java程序开发而言,主要会使用JDK的两个命令:jav ...
- 零python基础--爬虫实践总结
网络爬虫,是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本. 爬虫主要应对的问题:1.http请求 2.解析html源码 3.应对反爬机制. 觉得爬虫挺有意思的,恰好看到知乎有人分享的一个爬虫 ...
- weixin://connectToFreeWifi/?apKey=协议如何跳转到微信客户端打开在wifi指定任意网页?
微信门店wifi接口,任意站跳转,跳转二维码长按识别加粉,接口支持动态传参数,支持微信支付等特殊接口对接. 代码如下使用 <head> <meta charset="utf ...
- Signalr实时通讯
我们直接来干货~~~~~~觉得好推荐一下哈 研究不易 参考--https://www.jb51.net/article/133202.htm 这是基本教程 下面是重点: 如果你想允许跨域 具体代码 ...
- Oracle游标介绍
Oracle游标使用详解: 游标: 用来查询数据库,获取记录集合(结果集)的指针,我们所说的游标通常是指显式游标,因此从现在起没有特别指明的情况,我们所说的游标都是指显式游标.要在程序中使用游标,必须 ...