Unity地面检测、跳跃

首先,如果不做跳跃、不需要人物从高处坠落时做出坠落动作,就并不一定要写地面检测。人物坠落时保持在地面上的动作,可以在空中跑步,如果对效果要求不高就问题不大。

地面检测

碰撞检测方案

判定离地的代码写在OnCollisionExit(),在地面上的代码写在了OnCollisionStay(),不能写在OnCollisionEnter(),因为人物如果先接触另一块地面,再离开这一块地面,OnCollisionExit()的效果覆盖了OnCollisionEnter(),人物被判断为离地。如果写在OnCollisionStay(),离开一块地面时OnCollisionExit()执行一次,而OnCollisionStay()一直执行,人物还被判断为在地面上。坠落伤害的代码则可以放OnCollisionEnter()。

但是这样写还有严重的问题:下坡的时候先靠animator水平移动,再靠重力下落贴紧斜面,onGround会不停变成false导致人物做出坠落姿势或不能跳跃。

void OnCollisionStay(Collision collision){
        if(CheckIsGround(collision.gameObject)){//地面检测在Stay里,时时都要检测
            myCharacter.animator.SetBool(MyCharacter.onGroundPara,true);
        }
    }
    void OnTriggerExit(Collider other){
        if(CheckIsGround(other.gameObject)){//检测离地
            myCharacter.animator.SetBool(MyCharacter.onGroundPara,false);
            rigidbody.velocity=myCharacter.animator.velocity;
        }
    }
    static int speedToHurt=9,fallHurtDamage=40,speedToDeath=15,fallDeathDamage=120;//固定跌落伤害
    void OnCollisionEnter(Collision collision){
        if(CheckIsGround(collision.gameObject)){
            if(collision.relativeVelocity.magnitude>speedToDeath){
                myCharacter.TakeDamage(fallDeathDamage,MyGameManager.fallHint);
            }
            else{
                if(collision.relativeVelocity.magnitude>speedToHurt){//跌落伤害
                    myCharacter.TakeDamage(fallHurtDamage,MyGameManager.fallHint);
                }
            }
        }
    }

补救方法:在人物碰撞体下端套一个稍大的触发器碰撞体,这个碰撞体离地时才判定离地。地面检测触发器为了和碰撞体区分开,要么就挂在其他节点上。这样让做一个人物的流程更复杂了。

Unity地面检测、跳跃

在判断开始坠落时要执行

rigidbody.velocity=myCharacter.animator.velocity;

在坠落中继承人物的水平速度。而在落地后这个刚体速度不用设0,刚体会由于摩擦自动停下。

速度检测方案

现实世界中人类对坠落的反应好像并不是因为脚离地,而是因为下落的加速度达到了一定值。比如在加速下落的电梯里人的脚着地,但是会感觉到在下落。rigidbody没有加速度字段,但是可以通过rigidbody.velocity.y达到一定值来判断。

float fallSpeedLastFrame;
public float fallSpeedThreshold=-3;
void Update(){
   if(fallSpeedLastFrame>=fallSpeedThreshold&&myCharacter._rigidbody.velocity.y

物理效果

如果角色挂有RigidBody,可以通过rigidBody.velocity=jumpSpeed*Vector3.up实现。如果角色使用Animator的Root Motion移动,可以通过

rigidbody.velocity=new Vector3(_animator.velocity.x,jumpSpeed,_animator.velocity.z);

实现移动中跳跃,跳跃中保持起跳的速度。

动画效果

简单的跳跃只需要滞空动画。如果想做得更逼真,可以添加起跳和落地动画。我这里做滞空和落地动画。落地动画因为本身属于过渡动画,为了避免自动过渡出现不想要的效果,应该把滞空到落地、落地到站立的过渡设置尽量短。

Unity地面检测、跳跃Unity地面检测、跳跃

程序判定

满足玩家输入跳跃&&人物在地面上就跳跃。定义一个bool onGround记录是否在地上,可以在脚本里或动画参数。

问题记录

跑步中跳跃有一定概率出现在空中跑步,看状态机显示进入跳跃状态后立刻退出进入了跑步状态。跳跃状态的退出条件是onGround==true,也就是说进入跳跃状态后立刻满足了退出的条件。

Unity地面检测、跳跃

解决方法:稍微增加了跑步到跳跃状态过渡的时长。

Unity地面检测、跳跃

上一篇:Leetcode面试经典150题-39.组合总数进阶:40.组合总和II
下一篇:SEO人员,建立外链的注意事项有哪些?