Непоследовательный прыжок в Unity в зависимости от значения Y - PullRequest
0 голосов
/ 31 августа 2018

Я создаю игру в Unity, в которой вы перемещаетесь с помощью WASD и места для прыжков. Это мой код:

using UnityEngine;

public class PlayerMovement : MonoBehaviour {

    public Rigidbody rb;
    public bool canJump;

    void FixedUpdate () {
        if (Input.GetKey("w"))
        {
            rb.AddForce(0, 0, 750 * Time.deltaTime, ForceMode.Acceleration);
        }

        if (Input.GetKey("a"))
        {
            rb.AddForce(-750 * Time.deltaTime, 0, 0, ForceMode.Acceleration);
        }

        if (Input.GetKey("s"))
        {
            rb.AddForce(0, 0, -750 * Time.deltaTime, ForceMode.Acceleration);
        }

        if (Input.GetKey("d"))
        {
            rb.AddForce(750 * Time.deltaTime, 0, 0, ForceMode.Acceleration);
        }

        if (canJump)
        {
            if (Input.GetKeyDown("space"))
            {
                rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
                Debug.Log("jump");
                canJump = false;
            }
        }

        Vector3 v = rb.velocity;
        v.y = 0;
        v = Vector3.ClampMagnitude(v, 6);
        v.y = rb.velocity.y;
        rb.velocity = v;
    }

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.name == "Ground")
        {
            canJump = true;
        }
    }

    void OnCollisionExit(Collision other)
    {
        if (other.gameObject.name == "Ground")
        {
            canJump = false;
        }
    }
}

Но когда я прыгаю, он иногда поднимается довольно высоко, а иногда почти не прыгает. Я проверил, имеет ли какое-либо значение нажатие клавиши «пробел», и это не так. Я пытался использовать ForceMode.Impulse и ForceMode.VelocityChange, но прыжки по-прежнему противоречивы.

Я также заметил, что игрок прыгает высоко в воздухе только тогда, когда его значение Y на полу составляет около 0,23. Это также может быть ~ 0,16, как это, и он не прыгает очень высоко.

Это ~ 0,16 0.16 И это ~ 0,23 0.23

Самый низкий скачок поднимает его до значения Y ~ 0,7, но самый высокий скачок достигает примерно 4,83.

Если у кого-то есть идеи, я был бы очень признателен.

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

хорошо, если вам нужно срочно исправить это. Возьмите FPS-символ единства по умолчанию, изучите его свойства и компоненты и попробуйте сделать то же самое с вашим собственным объектом. Вы можете перейти к деталям позже

0 голосов
/ 31 августа 2018

Что я обычно делаю, так это проверяю, иду ли я вверх или вниз. Я принимаю только проверку земли, если иду вниз.

void OnCollisionEnter(Collision other)
{
    if (other.gameObject.name == "Ground" && rb.velocity.y < 0)
    {
        canJump = true;
    }
}

Тем не менее, вы используете getKeyDOWN, поэтому речь идет не о удержании места и т. Д.

Итак, следующее, что я могу порекомендовать, это: установить speed.y на 0 перед прыжком.

if (Input.GetKeyDown("space"))
{
    Vector3 vel = rb.velocity;
    vel.y = 0;
    rb.velocity = vel;
    rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
    // ...
}

edit : Подождите, моя первая мысль была «он использует getKey и держит пробел», моя вторая мысль была: «он пропустил Time.deltaTime». Но теперь я вижу это:

Вы использовали Input.Get... в FixedUpdate!

Позвольте мне объяснить:

Все входы оцениваются перед вызовом всех Update. Как вы можете видеть в Порядке выполнения Входные события обрабатываются непосредственно перед обновлением.

Теперь, в зависимости от частоты кадров, обновление вызывается часто или редко, по сравнению с (почти) постоянной FixedUpdate.

Таким образом, FixedUpdate может вызываться несколько раз между Update вызовами. А это значит, что входные события запускались один раз.

ТАК Я должен предположить, что Input.GetKeyDown(Key.SPACE) будет истинным в нескольких FixedUpdates!

Легко исправить:

bool jump_pressed = false;

void Update()
{
    if(Input.GetKeyDown("space"))
    {
        jump_pressed = true;
    }
    if(Input.GetKeyUp("space"))
    {
        jump_pressed = false;
    }
}

void FixedUpdate()
{
    if(jump_pressed)
    {
        jump_pressed = false;
        rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
        // etc...
    }
}

Таким образом, вы просто обрабатываете всю логику ввода в обновлении, а остальные выполняете в фиксированном обновлении.

Конечно, jump_pressed нужно установить в false в FixedUpdate, потому что в противном случае он останется истинным несколько раз FixedUpdate.

edit2 : Я снова посмотрел ваш код. Что бы вы ни делали, независимо от того, находится ли оно в FixedUpdate или Update, не используйте Time.deltaTime в AddForce.

AddForce будет манипулировать скоростью. И скорость используется в каждом PhysicsUpdate для перемещения преобразования. Но PhysicsUpdate / FixedUpdate пытается работать с (почти) фиксированной скоростью, тогда как Time.deltaTime дает вам истекшее время последнего (Обновления) кадра.

Если вы перемещаете преобразование самостоятельно (position += ...) - используйте Time.deltaTime. Но не используйте его, когда используете AddForce.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...