草庐IT

【Unity3D Debug】跳跃时的地面检测:“CharacterController.isGrounded的值总是为false”的原因与解决方案

圣☆哥 2023-04-04 原文

【Unity3D Debug】跳跃时的地面检测:“CharacterController.isGrounded的值总是为false”的原因与解决方案

FPS控制器中处理跳跃时需要进行角色与地面的碰撞检测,如果使用Character Controller,会发现有一个isGrounded属性,其描述如下:

isGrounded: Was the CharacterController touching the ground during the last move?

其实际意思是上一次调用CharacterController.Move时有没有触地。

isGrounded如果恒为false:其一,可能没有在判断其值之前调用Move函数;其二, 有可能是因为没有将其判断语句放在正确的位置,比如在Y轴方向的移动操作之前就进行该属性的判断,这时候可能还没有触地,像如下的代码就会导致isGrounded恒为false。

    // 根据curInput处理处理角色的真实移动
    public void UpdateMove()
    {
        if (isDead)  // 角色死亡
            return;
        float curSpeed = moveSpeed;
        dealWithMoveSpeed(ref curSpeed);  // 根据持有物确定移动速度
        Vector3 v = transform.TransformDirection(curMoveXZInput);  // 别忘了转为世界坐标系下的向量

        // 处理XZ平面的移动
        cc.Move(v * curSpeed * Time.deltaTime);  // Move方法传入的向量解读为世界坐标系下的向量       

        // 处理重力与起跳
        if (cc.isGrounded) 
        {
            velocity.y = -2f;  // 设为负数,确保在地面时能恒定接触地面,而不会误判为false
        }
        
        if(Input.GetKeyDown(KeyCode.Space) && cc.isGrounded)
        {
            //    m*g*h = 0.5*m*v_y0^2 - 0 -> v_y0 = sqrt(2*g*h)
            velocity.y = Mathf.Sqrt(-2f * GameManager.gravity * jumpHeight);
        }
        velocity.y += GameManager.gravity * Time.deltaTime;  // dv = g*t
        cc.Move(velocity * Time.deltaTime);  // 处理y轴方向的移动       
    }   

正确的做法是,把含有isGrounded的判断语句放在施加重力以及Y轴方向的Move之后,如下代码所示(可以和上面的代码对比一下)。

    // 根据curInput处理处理角色的真实移动
    public void UpdateMove()
    {
        if (isDead)  // 角色死亡
            return;
        float curSpeed = moveSpeed;
        dealWithMoveSpeed(ref curSpeed);  // 根据持有物确定移动速度
        Vector3 v = transform.TransformDirection(curMoveXZInput);  // 别忘了转为世界坐标系下的向量

        // 处理XZ平面的移动
        cc.Move(v * curSpeed * Time.deltaTime);  // Move方法传入的向量解读为世界坐标系下的向量       
        // 处理重力与起跳
        velocity.y += GameManager.gravity * Time.deltaTime;  // dv = g*t
        cc.Move(velocity * Time.deltaTime);  // 处理y轴方向的移动       
        if (cc.isGrounded)  // Code1
        {
            velocity.y = -2f;  // 设为负数,确保在地面时能恒定接触地面,而不会误判为false
        }
        if(Input.GetKeyDown(KeyCode.Space) && cc.isGrounded)
        {
            //    m*g*h = 0.5*m*v_y0^2 - 0 -> v_y0 = sqrt(2*g*h)
            velocity.y = Mathf.Sqrt(-2f * GameManager.gravity * jumpHeight);
        }
    }   

另外,观察上面的代码,可以发现:为了确保触地,当isGrounded为true时,将Y轴方向的速度设为了一个较小的负值,这是为了确保在地面时能稳定触碰地面,避免isGrounded误判为false。

最后,如果只需要角色与部分层进行碰撞检测,可以通过Edit → \rightarrow Project Settings → \rightarrow Physics → \rightarrow Layer Collision Matrix,即修改层的碰撞矩阵,确认角色层所在的行和列,勾选与之交互的层,并取消其他层即可。举个例子,对于FirstPerson层,我只要确保它与Ground层、UI层进行碰撞,则影响范围和相关勾选状态如下图红线所示。

笔者没有研究CharacterController.Move和.isGrounded的具体实现(Unity没有公开其源码),以上结论仅来自于笔者的个人实践,可能存在局限性。若存有谬误,欢迎大佬们批评指正!

有关【Unity3D Debug】跳跃时的地面检测:“CharacterController.isGrounded的值总是为false”的原因与解决方案的更多相关文章

  1. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  2. 【高数】用拉格朗日中值定理解决极限问题 - 2

    首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有,  也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加

  3. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  4. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  5. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

  6. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  7. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  8. ruby - 如何更快地解决 project euler #21? - 2

    原始问题Letd(n)bedefinedasthesumofproperdivisorsofn(numberslessthannwhichdivideevenlyinton).Ifd(a)=bandd(b)=a,whereab,thenaandbareanamicablepairandeachofaandbarecalledamicablenumbers.Forexample,theproperdivisorsof220are1,2,4,5,10,11,20,22,44,55and110;therefored(220)=284.Theproperdivisorsof284are1,2,

  9. ruby - 为什么这些方法没有解决? - 2

    这个问题在这里已经有了答案:WhydoRubysettersneed"self."qualificationwithintheclass?(3个答案)关闭29天前。给定这段代码:classSomethingattr_accessor:my_variabledefinitialize@my_variable=0enddeffoomy_variable=my_variable+3endends=Something.news.foo我收到这个错误:test.rb:9:in`foo':undefinedmethod`+'fornil:NilClass(NoMethodError)fromtes

  10. 电脑启动后显示器黑屏怎么办?排查下面4个问题,快速解决 - 2

    电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑

随机推荐