Как вы можете проверить, движется ли объект / не движется? - PullRequest
0 голосов
/ 12 февраля 2019

Я хочу сделать простой сценарий, чтобы при нажатии на экран шарик в игре переместился (20000 * Time.deltaTime) вправо, а затем, если я нажму еще раз, он переместится в левую сторону.и затем вправо и т. д.

Мне удалось заставить шар двигаться вправо, но мне нужно, чтобы он дождался окончания анимации, потому что мне нужно проверить, не нажал ли игрок снова (если он это сделалМне нужно проверить, в каком направлении двигаться мяч).Я перепробовал много методов, которые я нашел в Интернете, например, проверяя, если Rigidbody.velocity.magnitude == 0.0f, что означает, что мяч не движется ..

public Rigidbody rb;
public Transform PlayerPosition;
// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        rb.AddForce(20000 * Time.deltaTime, 0, 0); // moving ball to the right
        while (rb.velocity.magnitude != 0.0f) // I tried to check until the ball is not moving 
        {

        }
        Debug.Log(PlayerPosition.position.x);
    }
}

И вот моя последняя попытка:

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        rb.AddForce(20000 * Time.deltaTime, 0, 0); // moving ball to the right
        if(rb.velocity.magnitude < 0.05f) // if i click the ball it just prints it and not wating for the ball to not move
        {
            Debug.Log(PlayerPosition.position.x);
        }
    }
}

Я ожидал, что вывод будет ждать, пока анимация не закончится, но вместо этого он напечатал vaule (x) в тот момент, когда я щелкну мышью.

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Я думаю, что вы хотите переместить его, если он остановлен, а затем вызывать AddForce только тогда, когда он простаивает:

var wasMovingLastTime = false;    

void Update()
{
    var isMoving = rb.velocity.magnitude > 0f;

    if (wasMovingLastTime && !isMoving)
    {
        /// Has just finished moving
        Debug.Log(PlayerPosition.position.x);
    }

    if (Input.GetMouseButtonDown(0))
    {
        if (!isMoving)
        {
            rb.AddForce(20000 * Time.deltaTime, 0, 0);
        }
    }

    wasMovingLastTime = isMoving;
}
0 голосов
/ 13 февраля 2019

Первая

rb.velocity.magnitude != 0.0f

будет почти всегда будет true из-за с плавающей точкой одинарной точности : два значения с плавающей запятой, даже если они кажутся одинаковыми логическимискорее всего, нет.

Таким образом, вы можете либо использовать порог, как вы уже пытались

if(rb.velocity.magnitude <= 0.5f)

, либо использовать Mathf.Approximately , который использует очень маленький Epsilon или порог для сравнения

if(Mathf.Approximately(rb.velocity.magintude, 0))

Чем звучит, как будто вы хотите подождать, пока мяч перестанет двигаться, и затем выведите позицию - как, например, для бильярдной игры.Таким образом, на самом деле, кажется, что Анимация не задействована.

В большинстве случаев, когда вы думаете / говорите о «анимации», вы на самом деле имеете в виду «делать что-то со временем», чтобы не путать с использованиемAnimator или Animation компонент с AnimationClip s в Unity.

Вы можете / должны использовать Coroutine для этого:

public Rigidbody rb;
public Transform PlayerPosition;

// a flag to make sure there is only one animation at a time
private bool isMoving;

// a flag for altering between left and right movement
private bool isMovingRight;

// Update is called once per frame
void Update()
{
    // only allow clicks while not moving already
    if (!isMoving && Input.GetMouseButtonDown(0))
    {
        // stop further input until not moving anymore
        isMoving = true;

        // add the force 
        // (you might btw want to skip that Time.deltaTime here it makes no sense)
        rb.AddForce(isMovingRight ? 20000 : -20000 * Time.deltaTime, 0, 0);

        // alter the direction for the next call
        isMovingRight = !isMovingRight;

        // if you rather want to be able to interrupt the current animation by clicking again
        // remove the isMoving flag and instead use this
        //StopCoroutine(WaitForMoveStops());  

        // Start the routine
        StartCoroutine(WaitForMoveStops());
    }
}

private IEnumerator WaitForMoveStops()
{
    // Inside a Coroutine while is okey now
    // as long as you yield somwhere

    // check if velocity is below threshold
    while (!Mathf.Approximately(rb.velocity.magnitude, 0) 
    {
        // yield in simple words means "leave" this method here, render the frame
        // and than continue from here in the next frame
        yield return null;
    }

    // I would now hard reset the velocity just to be sure
    rb.velocity = Vector3.zero;

    Debug.Log(PlayerPosition.position.x);

    // whatever you want to do now

    // reset the flag to allow input again
    isMoving = false;
}
0 голосов
/ 12 февраля 2019

Редактировать

Вам необходимо проверить, продолжает ли ваша анимация воспроизводиться.Вы проверяете, только если ваша скорость больше 0,05f, что правильно распечатывает выписку.

Используйте Animation.IsPlaying(string name).Одно предостережение в том, что этот метод вернет false для того же кадра Update, который был вызван, поскольку технически анимация не началась до тех пор.

void Update()
{
    if (!rb.velocity.magnitude <= 0.01f && !Animation.IsPlaying(nameOfAnimation))
    {
        Debug.Log("We're not moving and the animation is not playing");
    }
}

Оригинал

Вам не нужно использовать while в своем методе Update.

Использовать оператор if внутри вашего Update

void Update()
{
    if (rb.velocity.magnitude > 0.01f) Debug.Log("We're moving!");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...