2016-01-27 3 views
0

Привет!Мой персонаж делает неожиданный 3-й прыжок в Unity2D

В настоящее время я работаю над 2D-платформерной игрой в движке Unity, где я создал персонажа, который может забить doubleblejump.
В начале все было очень хорошо, но теперь я понял, что есть ошибка в игре, которая позволяет ему выполнить третий прыжок (по какой-то причине). И я не могу ради этого понять, в чем проблема.

PlayerController.cs

using UnityEngine; 
using System.Collections; 

public class PlayerController : MonoBehaviour { 

    /* 
    TODO: Find out why the character ocationally 
    gets 3 jumps instead of 2. 
    I think it's the "isGrounded" that returns 
    a false posetive. 
    */ 

[Header("Ground Recognition")] 
public BoxCollider2D groundCollider; 
public LayerMask groundAbles; 

[Header("Audio")] 
public GameObject jumpSound = null; 

[Header("Visual")] 
public GameObject jumpEffect = null; 


float speed = 5f; 
int maxJumps = 2; 
int currentJumps = 0; 

bool isGrounded = false; 
float boundsLength = 0; 

Vector3 movement; 
// Use this for initialization 
void Start() { 

} 

// Update is called once per frame 
void Update() { 
    CheckGroundCollision(); 
    JumpLogic(); 

    movement = new Vector3(Input.GetAxis("Horizontal") * speed, 0, 0); 
    movement *= Time.deltaTime; 
    transform.position += movement; 

    CheckGroundCollision(); 
} 

void CheckGroundCollision() 
{ 
    isGrounded = groundCollider.IsTouchingLayers(groundAbles); 
} 

void JumpLogic() 
{ 

    if (isGrounded) 
     currentJumps = 0; 

    if (Input.GetButtonDown("Jump") && currentJumps < maxJumps) 
    { 
     GameObject newJumpSound = (GameObject)GameObject.Instantiate(jumpSound, (Vector2)transform.position, transform.rotation); 
     GameObject newJumpEffect = (GameObject)GameObject.Instantiate(jumpEffect, (Vector2)transform.position - new Vector2(0, 0.25f), transform.rotation); 
     GameObject.Destroy(newJumpEffect, 0.2f); 
     GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, 0); 
     GetComponent<Rigidbody2D>().AddForce(new Vector2(0, 10), ForceMode2D.Impulse); 
     currentJumps++; 
     CheckGroundCollision(); 
    } 
} 
} 

Вся помощь ценится!

+0

как тест, попробуйте установить maxjumps на 1. и посмотреть, сможете ли вы получить 2 прыжка. это может быть порядок операций, и вы получаете isGrounded = true после нажатия прыжка, но перед тем, как покинуть контакт с землей. –

+0

Можете ли вы отлаживать или печатать какую-либо информацию во время ее работы? Мне было бы любопытно, если 'isGrounded' вызывает какие-либо проблемы и преждевременно перезагружает' currentJumps'. – Ian

+0

Я протестировал теорию, и проблема действительно основана на том, что currentJumps преждевременно перезагружается! – VonRiddarn

ответ

1

В void JumpLogic(), вы звоните

currentJumps++; 
CheckGroundCollision(); 

Самый первый раз, когда вы нажмете на прыжок ключ, currentJumps становится 1 (currentJumps ++), но затем isGrounded снова становится истинным (потому что физика не была применена но в текущем фрейме, и персонаж все еще касается наземной прокладки). Таким образом, в следующий раз вызывается JumpLogic(), currentJumps сбрасывается до нуля из-за if (isGrounded) currentJumps = 0; перед запуском кода перехода.

Предлагаю удалить последний звонок на CheckGroundCollision(); внутри void JumpLogic(). Они оба вызваны внутри Update() в любом случае, в порядке, который выглядит так, как будто это сработает.

Я надеюсь, что это поможет!

UPDATE: Я только что заметил, что вы также призывают CheckGroundCollision(); во второй раз в Update() себя. Это также приведет к сбросу переменной перехода.

Попробуйте эту модификацию исходного кода:

void Update() { 
    CheckGroundCollision(); 
    JumpLogic(); 

    movement = new Vector3(Input.GetAxis("Horizontal") * speed, 0, 0); 
    movement *= Time.deltaTime; 
    transform.position += movement; 

    //** NOTE- REMOVED THIS LINE 
} 

... 

void JumpLogic() 
{ 

    if (isGrounded) 
     currentJumps = 0; 

    if (Input.GetButtonDown("Jump") && currentJumps < maxJumps) 
    { 
     GameObject newJumpSound = (GameObject)GameObject.Instantiate(jumpSound, (Vector2)transform.position, transform.rotation); 
     GameObject newJumpEffect = (GameObject)GameObject.Instantiate(jumpEffect, (Vector2)transform.position - new Vector2(0, 0.25f), transform.rotation); 
     GameObject.Destroy(newJumpEffect, 0.2f); 
     GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, 0); 
     GetComponent<Rigidbody2D>().AddForce(new Vector2(0, 10), ForceMode2D.Impulse); 
     currentJumps++; 

     //** NOTE- REMOVED THIS LINE 
    } 
} 

Я надеюсь, что помогает!

+0

Я попытался удалить его, но проблема не устранена. Недавно я подтвердил, что проблема в том, что мой currentJumps досрочно перезагружается. – VonRiddarn

+0

Попробуйте изменить порядок 'CheckGroundCollision();' и 'JumpLogic();' inside Update ...наряду с изменением, которое я предложил выше. – andeart

+0

Это еще хуже. Теперь тройной прыжок работает как двойной прыжок. (Он всегда может сделать триплекс) – VonRiddarn

0

Я предлагаю разрешить коллайдеру диктовать игровому контроллеру состояние isGrounded, а не запрашивать коллайдер. Например, продолжая andeart's предложения, ваш код может выглядеть как следующий

void Update() { 
    JumpLogic(); 

    movement = new Vector3(Input.GetAxis("Horizontal") * speed, 0, 0); 
    movement *= Time.deltaTime; 
    transform.position += movement; 
} 

//let the collider indicate to the player controller when 
//a collision occurs, then determine if this collision is relevant 
void OnCollisionEnter2D(Collision2D coll) { 
    if(coll.IsTouchingLayers(groundAbles))  
     isGrounded = true; 

    // or do some other check using layers or tags .... 
} 

void JumpLogic() 
{ 
    if (isGrounded) 
     currentJumps = 0; 

    if (Input.GetButtonDown("Jump") && currentJumps < maxJumps) 
    { 
     GameObject newJumpSound = (GameObject)GameObject.Instantiate(jumpSound, (Vector2)transform.position, transform.rotation); 
     GameObject newJumpEffect = (GameObject)GameObject.Instantiate(jumpEffect, (Vector2)transform.position - new Vector2(0, 0.25f), transform.rotation); 
     GameObject.Destroy(newJumpEffect, 0.2f); 
     GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, 0); 
     GetComponent<Rigidbody2D>().AddForce(new Vector2(0, 10), ForceMode2D.Impulse); 
     currentJumps++; 
    } 
} 

См Collider2D.IsTouchingLayers особенно нижний пункт, который предполагает, что метод IsTouchingLayers не может дать наиболее Acurate результат относительно коллайдера.