统一射线广播如何防止双重跳跃问题

时间:2019-11-22 15:58:26

标签: c# unity3d

我正在尝试防止播放器跳两次,因为我正在使用Raycast检查播放器是否在地板层中。我的解决方案有时可行,但有时它可以使播放器翻倍。

这是我的代码:

void Movement()
{
    float movement = Input.GetAxis("Horizontal");
    Vector3 playerVelocity = new Vector3(movement*speed, myRigidbody.velocity.y, speed);

    myRigidbody.velocity = playerVelocity;


    if (Input.GetKeyDown("space") && isGrounded)
    {
        Vector3 jumpVelocity = new Vector3(0f, jumpSpeed, 0f);
        myRigidbody.velocity += jumpVelocity;
        isGrounded = false;
        Debug.Log("floor:"+isGrounded);
        anim.SetInteger("AnimationPar", 3);
        myAudioSource.Stop();
        AudioSource.PlayClipAtPoint(jumpSound,transform.position, volumeSoundEffects);
    }
    else if (isGrounded && !myAudioSource.isPlaying && !levelFinished)
    {
        myAudioSource.Play();
    }
    if (!isGrounded)
    {
        IsGrounded();
    }

}

void IsGrounded()
{        
    RaycastHit hit;
    int mask = 1 << LayerMask.NameToLayer("Floor");

    if (Physics.Raycast(transform.position, Vector3.down, out hit, 0.01f, mask))
    {
        //Debug.Log("Is touching floor");
        isGrounded = true;
        Debug.Log("floot:" + isGrounded);
        anim.SetInteger("AnimationPar", 1);
        if (!myAudioSource.isPlaying)
        {
            myAudioSource.Play();
        }            
    }
}

在Update中调用Movement方法。我认为也许IsGrounded方法被调用得很快,而播放器仍然靠近地面。

2 个答案:

答案 0 :(得分:0)

防止重复跳转的一种简单方法是使用计数器而不是光线投射,这确实使一切变得容易。在代码的这一部分放置一个计数器:

  if (Input.GetKeyDown("space") && isGrounded && counter <2)
        {


  Vector3 jumpVelocity = new Vector3(0f, jumpSpeed, 0f);
counter++;

答案 1 :(得分:0)

我目前无法调试代码,但是另一种方法是使用OnCollisionEnter和OnCollisionExit 您可以检测到玩家与之碰撞的所有事物,如果其中之一是地板,那么它可能已经搁浅了。但是有可能在跌倒时触摸玩家侧面的地板,以避免这种情况,请使用接地的方法。您说它确实有效,但有时会失败。因此,尝试以下操作:

void OnCollisionEnter (Collision col) 
{
   if(col.gameobject.layer == LayerMask.NameToLayer("Floor") && IsGrounded())
   {
       isGrounded = true;
   }
}
void OnCollisionExit (Collision col) 
{
   if(col.gameobject.layer == LayerMask.NameToLayer("Floor") && !IsGrounded())
   {
       isGrounded = false;
   }
}

那是未经测试的代码,所以我不是100%确定它是否会工作。由于IsGrounded可能仍然可以向地面发出光线,因此出口可能不起作用。但是,如果您在关卡中正确处理图层/碰撞,则可以完全删除IsGrounded调用。

到目前为止,这并不是完美的解决方案,但它可能会起作用。