前言
上学期就在学习unity了,毕竟梦想着做一名游戏开发者,之前忙着学做模型,还想着先把模型学好了再开始学unity。有一天突然发觉,模型不是一时半会能学好的,模型和unity可以并行。
正文
之前写过一些移动跳跃的脚本,网上的教程也看了很多,总是不满意。
难点在于是否在地面上的碰撞检测,用过很多方法。
Rigidbody组件
用Rigidbody组件做人物控制器,判断碰撞点法线的y值,即collision.getContact(0).normal.y > 0,就说明底部碰撞到东西,可以跳跃,添加一个向上的力,rigidbody.addForce(Vecter3.up * force)。
第一个坑来了,XY轴向上不移动时,跳跃高度正确,但是如果XY轴向上有移动时,跳跃高度明显不正确,到现在没想清楚原因。
第二个坑是Rigidbody组件上台阶不好写,而且过程中可能会发生碰撞。
Rigidbody组件的好处在于落地之后如果陷入地面它会自动回弹起来。
Character Controller组件
也用过网上讲得最多的,在Character Controller脚下加一个碰撞体进行碰撞检测,但我遇到的问题是,落地之后碰撞体可能会陷入地面,导致在后面需要跳起时不能正常跳起。
最后我使用的是Character Controller组件自带的碰撞检测,即属性isGrounded。
这个属性是指上次调用Move函数的期间,胶囊体底部是否发生碰撞,这就可以很好地进行碰撞检测。
但是这里也有一个坑,我之前的想法是在isGrounded为false时,模拟物理跳跃和下落过程。一旦物体落地,就将Y轴向上的速度置为0。
由于我在Y方向上的位移是由Y轴向上的速度与时间的乘积,所以我理所应当认为此时物体应该不移动了,isGrounded也应该一直为true。
但是我发现当物体落地之后,我点击空格键,不能准确响应跳跃。
然后我就在每一帧输出isGrounded,发现即使在地上,isGrounded的值也并不是唯一的,而是在true和false之间来回切换,我当时就懵了。
原因及解决方法
后来才想清楚,因为我在物体落地时将Y轴向上的速度置为0,但是由于速度是float类型,所以这个速度会在0附近来回横跳,所以导致物体一会往上,一会往下,导致isGrounded的值也往复横跳。
解决方法是每一帧都让竖直方向上的位移为负值,-0.01f即可,这样就保证在地上时,isGrounded一直为true。