Как остановить сопротивление после достижения определенной скорости

У меня есть следующий код, который добавляет силу к hardbody2d в случайном направлении и пытается установить линейное сопротивление равным 0 при достижении определенной скорости, по существу позволяя игровому объекту медленно уплывать.

Проблема в том, что перетаскивание как бы сразу установлено на 0, и я не понимаю, почему, и поэтому я не могу решить проблему.

void Update () {
    if (Input.GetKeyDown ("space")) {
        rb.velocity = Vector3.zero;
        Vector3 dir = Random.onUnitSphere;
        rb.AddForce (dir * 10, ForceMode2D.Impulse);
    }

    if (rb.velocity.magnitude <= 1) {
        rb.drag = 0;
    }
}

Спасибо, Круз.


person Crouzilles    schedule 19.06.2017    source источник
comment
Вы устанавливаете скорость на 0 при попадании в пространство, что устанавливает величину на 0. Сила, которую вы прикладываете, вероятно, не устанавливает скорость.величина на <= 1, что дает вам rb.drag = 0. Вы никогда не меняете rb.drag после установки один раз.   -  person Fredrik Schön    schedule 19.06.2017
comment
Спасибо @Maakep. Я предположил, что добавление силы к твердому телу гарантирует, что его скорость будет установлена ​​на новое значение в новом направлении, и что значение величины также будет следовать.   -  person Crouzilles    schedule 19.06.2017
comment
Я не проверял это, но я предполагаю, что это так, физика не рассчитывается в Update(). Обновление запускается в каждом кадре, поэтому я предполагаю, что в каком-то кадре оно не перемещается выше 1 величины, что устанавливает сопротивление на 0 на все будущее. Вы можете легко проверить это, установив Debug.Log(rb.velocity.magnitude); в методе обновления. хотелось бы услышать результаты   -  person Fredrik Schön    schedule 19.06.2017
comment
Один из способов исправить это, вероятно, состоял бы в том, чтобы просто сделать: else if (rb.drag != yourMagnitude) { rb.drag = yourMagnitude; } на этом if. Так что он плавает на низких скоростях и уменьшается на высоких скоростях.   -  person Fredrik Schön    schedule 19.06.2017


Ответы (1)


Как сказал @Maakep, проблема возникает из-за того, что вы устанавливаете скорость Rigidbody на 0 и сразу после этого проверяете, равна ли эта скорость <= 1 (сила применяется только позже).

Чтобы решить вашу проблему, вы можете сделать что-то вроде этого:

public bool applyNextFrame = false;

protected override void Update()
{
    if(applyNextFrame && rb.velocity.magnitude <= 1)
    {
        rb.drag = 0;
        applyNextFrame = false;
    }

    if(Input.GetKeyDown(KeyCode.Space))
    {
        rb.velocity = Vector3.zero;
        Vector3 dir = Random.onUnitSphere;
        rb.AddForce(dir * 10, ForceMode2D.Impulse);
        applyNextFrame = true;
    }
}

Имейте в виду, что это решение далеко не безупречно, так как у вас могут возникнуть проблемы, если ваша конфигурация Rigidbody (приложенная масса, перетаскивание и сила) применяет разные значения скорости: поэтому вы не сможете полностью контролировать когда перетаскивание достигнет 0 (это может быть полностью преднамеренным в зависимости от вашего проекта!) :)

Дополнительную информацию можно найти на диаграмме порядка выполнения, расположенной на этой странице: вы можете посмотрите, как внутреннее обновление физики происходит до Update() (когда вы вызываете rb.AddForce(...), оно фактически применяется только во время следующего внутреннего обновления физики).

Также обратите внимание, что я изменил Input.GetKeyDown("space") на Input.GetKeyDown(KeyCode.Space): это позволяет избежать проблем с опечатками, если вы ошибетесь при вводе space.

Надеюсь, это поможет

person Kardux    schedule 19.06.2017