В то время как бесконечный цикл с движущимся единым преобразованием - PullRequest
0 голосов
/ 30 августа 2018
while (transform.position != new Vector3(desX, desY))
{
    // 2 - Movement
    Vector3 movement = new Vector3(
        0.1f * desX,
        0.1f * desY,
        0);

    //movement *= Time.deltaTime;
    transform.Translate(movement);
}    

Эта часть моей программы дает сбой движку Unity, и я уверен, что это бесконечный цикл, но я не могу понять, почему или как это исправить.

Ответы [ 2 ]

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

Замораживает ваше приложение, потому что вы не даете другим сценариям возможности работать, если условие в цикле while не выполнено.

Чтобы исправить это, поместите этот код в функцию сопрограммы, затем добавьте yield return null; в цикл while. Это заставляет Unity ждать кадра после каждого цикла, поэтому другие сценарии могут запускать каждый кадр. Это должно решить проблему замораживания вне зависимости от того, завершается цикл while или нет. Я бы также предложил вам использовать Vector3.Distance, чтобы определить, когда вы находитесь рядом с пунктом назначения.

public float reachThreshold = 0.2f;

void Start()
{
    StartCoroutine(MoveBject());
}

IEnumerator MoveBject()
{
    float distance = Vector3.Distance(transform.position, new Vector3(desX, desY));

    while (distance > reachThreshold)
    {
        // 2 - Movement
        Vector3 movement = new Vector3(
            0.1f * desX,
            0.1f * desY,
            0);

        //movement *= Time.deltaTime;
        transform.Translate(movement);

        //Wait a frame
        yield return null;
    }
}

Если вы действительно хотите переместить GameObject на другую позицию с течением времени, см. этот пост.

0 голосов
/ 30 августа 2018
  1. Как правило, не выполняйте в while такие вещи, которые должны происходить на основе каждого кадра! (Спасибо Рон)
    Результатом while в лучшем случае будет то, что ваше приложение застрянет, пока в конечном итоге векторы не совпадут, что заставит объект «подпрыгнуть» на месте. В худшем случае они никогда не совпадают, и ваше приложение зависает навсегда.

    Вместо этого следует использовать метод Update(), который вызывается для каждого кадра, и просто перемещать объект на один шаг за кадр.

  2. Для сравнения векторов лучше использовать Vector3.Distance. Использование оператора == для Vector3 в принципе нормально, но внутренне оно делает что-то, равное

    Vector3.Distance(vectorA, vectorB) <= 0.00001f
    

    , который использует очень маленькое удержание, которое может не совпадать точно. Таким образом, используя Vector3.Distance, вы можете установить свой собственный порог, например, на 0.1, чтобы было легче сопоставлять.

     bool match = Vector3.Distance(transform.position, new Vector3(desX, desY) < 0.1f
    
  3. Для перемещения объекта к другому Unity фактически уже есть встроенный метод Vector3.MoveTowards например,

    transform.position = Vector3.MoveTowards(transform.position, new Vector3 (desX, desY), 0.1f);
    

    Это касается сравнения Векторов3, поэтому оно вам больше не нужно.

  4. Чтобы сделать его более плавным и сохраняющим рамку, вы уже правильно использовали Time.deltaTime. Без этого он будет двигаться 0.1 meters / frame, но ваша частота кадров может быть не стабильной. Использование Time.deltaTime делает его 0.1 meters / second, что почти во всех случаях является тем, чего вы на самом деле хотите достичь.

Итак, чтобы собрать его, ваш код должен выглядеть примерно так:

float desX;
float desY;

float moveSpeed = 0.1f;

void Update()
{
    var targetPosition = new Vector3 (desX, desY);

    transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
}

Обратите внимание, что в некоторых случаях MoveTowards по-прежнему недостаточно ретранслируемо, например, если вы хотите отслеживать столкновения или что-то. В этом случае см. здесь

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