详解Unity地面检测方案

1.普通射线

在角色坐标(一般是脚底),发射一根向下的射线(长度约0.2)

但是简单射线只适用于简单地形,实际使用中常常遇到以下问题

1.用collider去碰撞地面,某些时候会有一定的穿插,于是角色的最低点就可能穿透地面,你发射射线的点可能就到了地面以下,射线一直检测不到真正的地面,于是角色就一直悬空

2.角色走斜坡时,角色中点可能会离开地面一小段距离,这一小段距离往往就足够让判断机制误以为角色已经离地,如果你增加射线的长度,那么一定程度上能缓解斜坡问题,但是会降低跳跃判断的精度,精度过低就有可能出现:角色跳起,会有那么一小段距离,其实已经离地了,但是仍然返回了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;
}

5.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地面检测方案的详细内容,更多关于Unity地面检测方案的资料请关注我们其它相关文章!

(0)

相关推荐

  • 新手必看Unity2019 2020保姆级安装教程

    1.通过UnityHub安装unity UnityHub下载路径,UnityHub安装按照步骤来就可以了. 打开UnityHub,点安装. 3.选择自己要安装的版本,由于unity2019以上的可以在选择组件的时候选择安装sdk和ndk,所以建议选择unity2019版本以上的.在导处apk文件的时候需要sdk和ndk. 4.如果自己没有安装vs,那么在这里可以选择添加给unity添加vs组件:因为我想开发Andriod游戏,所以我选了Android Build Support,并勾选sdk和n

  • 聊聊Unity 自定义日志保存的问题

    前言 之前unity5.x在代码中写了debug.log..等等,打包之后在当前程序文件夹下会有个对应的"outlog.txt",2017之后这个文件被移到C盘用户Appdata/LocalLow/公司名 文件夹下面.觉得不方便就自己写了个 代码 using UnityEngine; using System.IO; using System; using System.Diagnostics; using Debug = UnityEngine.Debug; public class

  • 详解Unity 实现语音识别功能

    现在语音识别已经被广泛的应用到各个领域中,在Unity开发中,语音识别也非常受欢迎.大部分人都会选择科大讯飞的语音识别功能,但是在一些小的项目中,使用科大讯飞的就有点大材小用了.今天就介绍一下Unity自带的语音识别功能.说是语音识别,其实unity本身还是做不到的,Unity自带的语音识别功能其实是关键字识别.比如我在Unity中设定好一句话汇总的几个关键词.当我再说这句话的时候就会和识别到.经过测试发现当一句话中有八个关键字,这句话就会非常好的被识别出来. 接下来就一起来实现一下: 首先贴一

  • Unity实现文本转贴图

    本文实例为大家分享了Unity实现文本转贴图的具体代码,供大家参考,具体内容如下 导入字体 导入ttf字体,修改Character为Custom set,并填入Custom Chars: 可以看到,Unity为我们生成了对应的材质和贴图: 从上图可以看出: 1.Unity中Texture2D的坐标原点为左下角,和OpenGL相同,V坐标与DX相反. 2.某些字符被上下翻转,某些字符被顺时针旋转了90度 这两点需要特别注意. 原理分析 本文中使用的方法是创建一个Texture,然后利用Textur

  • Unity使用DoTween实现抛物线效果

    Unity使用DoTween实现抛物线效果,供大家参考,具体内容如下 概要 public partial class EMath { public static Vector3 Parabola(Vector3 start, Vector3 end, float height, float t) { float Func(float x) => 4 * (-height * x * x + height * x); var mid = Vector3.Lerp(start, end, t); r

  • Unity中 mesh生成斜坡的示例代码

    Mesh概念: Mesh是Unity中的一个组件,称为网格组件.通俗的讲,Mesh是指模型的网格,3D模型是由多边形拼接而成,而多边形实际上是由多个三角形拼接而成的.所以一个3D模型的表面其实是由多个彼此相连的三角面构成.三维空间中,构成这些三角形的点和边的集合就是Mesh. Mesh组成: 1.顶点坐标数组vertexes 2.顶点在uv坐标系中的位置信息数组uvs 3.三角形顶点顺时针或者逆时针索引数组triangles 4.MeshFiler组件,用于增加mesh属性 5.MeshRend

  • Unity报错InvalidOperationException: out of sync的解决

    Unity 报错 之 InvalidOperationException: out of sync 报错原文: InvalidOperationException: out of sync System.Collections.Generic.Dictionary2+Enumerator[System.Int32,UnityEngine.Transform].VerifyState () (at /Users/builduser/buildslave/mono/build/mcs/class/c

  • Unity 从UI中拖拽对象放置并拖动效果 附demo

    需求:点击UI,在场景中生成3D对象,对象跟随鼠标移动,放置后可再次拖拽对象,改变其位置.做了一个小Demo,如下图所示: 实现大致思路: 射线碰撞检测 对象空间坐标变换(世界坐标->屏幕坐标.屏幕坐标->世界坐标) 首先为要生成3D对象的UI添加一个鼠标监听事件,脚本如下: SelectImage.cs using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngin

  • Unity实现桌面反弹的示例代码

    一:演示视频 二:代码实现 using UnityEngine; public class Ball : MonoBehaviour { private Rigidbody rigid; private Vector3 lastDir; public float speed = 30; private void Awake() { rigid = GetComponent<Rigidbody>(); rigid.velocity = new Vector3(1, 0, 1) * speed;

  • 详解Unity地面检测方案

    1.普通射线 在角色坐标(一般是脚底),发射一根向下的射线(长度约0.2) 但是简单射线只适用于简单地形,实际使用中常常遇到以下问题 1.用collider去碰撞地面,某些时候会有一定的穿插,于是角色的最低点就可能穿透地面,你发射射线的点可能就到了地面以下,射线一直检测不到真正的地面,于是角色就一直悬空 2.角色走斜坡时,角色中点可能会离开地面一小段距离,这一小段距离往往就足够让判断机制误以为角色已经离地,如果你增加射线的长度,那么一定程度上能缓解斜坡问题,但是会降低跳跃判断的精度,精度过低就有

  • 详解Unity安卓共享纹理

    概述 本文的目的是实现以下的流程: Android/iOS native app 操作摄像头 -> 获取视频流数据 -> 人脸检测或美颜 -> 传输给 Unity 渲染 -> Unity做出更多的效果(滤镜/粒子) 简单通信 在之前的博客里已经说到,Unity 和安卓通信最简单的方法是用 UnitySendMessage 等 API 实现. Android调用Unity: //向unity发消息 UnityPlayer.UnitySendMessage("Main Cam

  • 详解小程序横屏方案对比

    前言 随着小程序api开放的功能日渐增多,小程序可以做到的功能和展现形式也越来越多,其中横屏的展现形式就是其中的一种,而实现横屏的方案也有多种,但是每种方案都有一定的缺陷,恰巧最近也在横屏方案上踩了不少坑,接下来就来和大家分享一下小程序的不同横屏方案的优劣(踩坑心得) 组件自带横屏方法 小程序中的媒体组件一般都会提供全屏的方法,而且全屏方法中会提供一个direction的全屏参数,可以通过这全屏参数将小程序旋转90度横屏展示,这是小程序中最简单的横屏方法. 这个方法优点在于调用的组件全屏方法做的

  • 详解Unity入门之GameObject

    GameObject和Component GameObject是游戏场景中真实存在的,而且有位置的一个物件 Component附属于GameObject,控制GameObject的各种属性 GameObject是由Component组合成的,Component的生命周期和GameObject息息相关.调用此GameObject的Destroy方法,它的子对象和对应的所有Component都会被销毁,但也可以一次只销毁一个Component 常见的Component: Component 作用 R

  • 详解Unity中的ShaderGraph入门使用教程

    一,ShaderGraph 简介 简介: Unity2018版本之后推出了一个可编程渲染管线工具ShaderGraph,让我们可以通过可视化界面拖拽来实现着色器的创建和编辑. 官方话术: Shader Graph 使您能够直观地构建着色器.您无需编写代码,而是在图形框架中创建和连接节点.Shader Graph 提供反映您的更改的即时反馈,并且对于不熟悉着色器创建的用户来说非常简单. Shader Graph 仅与可编写脚本的渲染管线 (SRP) 兼容,即高清晰度渲染管线 (HDRP) 和通用渲

  • 详解SQL死锁检测的方法

    sql server中的死锁是指进程之间互相永久阻塞的状态,下文就将为您介绍如何检测sql server死锁,希望对您有所帮助. 死锁(deadlock)指进程之间互相永久阻塞的状态,SQL可以检测到死锁,并选择终止其中一个事务以干预sql server死锁状态. 第一步:首先创建两个测试表,表goods_sort和goods 表goods_sort:创建并写入测试数据 IF EXISTS(SELECT name FROM sysobjects WHERE name='goods_sort' A

  • 详解android 人脸检测你一定会遇到的坑

    笔者今年做了一个和人脸有关的android产品,主要是获取摄像头返回的预览数据流,判断该数据流是否包含了人脸,有人脸时显示摄像头预览框,无人脸时摄像头预览框隐藏,看上去这个功能并不复杂,其实在开发过程中,遇到的问题也不多,全部都处理了,在正式推出前,这个产品在公司内部也测试了几个月,也没发现bug,但最近实施人员,在客户公司做实施时,反馈回来各种问题,这些问题有部分是程序bug,也有一部分是和硬件有关,因为测试环境有限,笔者无法对各种型号,各个厂家的硬件进行测试,这篇文章主要是记录,摄像头给我们

  • 详解Vue 换肤方案验证

    本文的换肤方案灵感来自于 element-ui 需求:网站换肤,主题切换.网站的主题色可以在几种常用颜色之间进行切换,还有相关图片.图标也要跟随主题进行切换. 不多说,先看下最终的实现效果: 文章由两部分组成:css切换,图片图标切换 css切换 1.在 static 目录下新建一个 styles 文件夹,在 styles 下新建一个 theme.scss 文件(项目使用了sass,会自动编译成css文件,如果没有使用这些预处理工具可以直接新建 theme.css),将需要替换的 CSS 声明在

  • 详解nodejs 配置文件处理方案

    前言 一般来说:一个好的项目配置应该满足以下条件: 依赖环境:配置根据具体运行环境从相应的文件读取 代码分离:配置项不仅可以从配置文件读取, 也可以从环境变量读取,使得安全隐秘的配置项与代码分离 易于使用:配置项应该是分层配置的,有助于查找条目和维护庞大的配置文件的,应该是容易组织和容易获取的,比如json结构 在多人开发 nodejs 项目的时候,没有规划好配置方案,配置文件的问题就很容易暴露出来. 痛点 在开发 nodejs 的工程中,遇到过三个痛点 部署环境不同: 开发.测试.生产环境的不

随机推荐