Почему мой объект не перестает двигаться на transform.Translate? - PullRequest
1 голос
/ 03 июня 2019

Я хочу, чтобы Объект заставлял другой Объект двигаться за каждое преобразование. Перевести, но Объект не останавливается, когда достигнет своего места назначения.

Я пробовал несколько вещей в своем сценарии, но у меня не было конкретной идеи, чтоможет быть проблема.Одна вещь: у меня есть несколько методов в моем коде, которые заставляют несколько вещей двигаться по-разному в разных местах.Итак, я написал небольшой метод, который выполняет определенный метод для Input.GetKey (), чтобы увидеть, будет ли он таким же, когда я не выполняю другой метод, кроме того, я закомментировал все, что вызывается в Update, чтобы убедиться.Никакой другой метод движения не должен влиять на объект.Поэтому я опубликую только уязвимый метод, который вызывается для GetKey в обновлении.

«transPointFirst» в «transPointFourth» - это пустые игровые объекты, переданные в Инспекторе.Я также проверил, перемещаются ли transPoints во время выполнения, но нет, одинаковые позиции в каждом кадре.

private void ElevateCaptain()
{
    targetRigid.isKinematic = true;

    var transFirst = new Vector3(transPointFirst.localPosition.x, transPointFirst.localPosition.y, 0);
    var transSecond = new Vector3(transPointSecond.localPosition.x, transPointSecond.localPosition.y, 0);
    var transThird = new Vector3(transPointThird.localPosition.x, transPointThird.localPosition.y, 0);
    var transFourth = new Vector3(transPointFourth.localPosition.x, transPointFourth.localPosition.y, 0);

    target.transform.Translate(transFirst * Time.deltaTime, Space.World);

    if (target.transform.position == transFirst)
        target.transform.Translate(transSecond * Time.deltaTime, Space.World);

    else if (target.transform.position == transSecond)
        target.transform.Translate(transThird * Time.deltaTime, Space.World);

    else if (target.transform.position == transThird)
        target.transform.Translate(transFourth * Time.deltaTime, Space.World);

    else if (target.transform.position == transFourth)
    {
        targetRigid.isKinematic = false;
    }
}

Итак, я хочу, чтобы моя цель переместилась к первому переводу, если он достигнут, перейдите квторой перевод и тд.Факт: цель движется в правильном направлении, но никогда не останавливается.Не имеет значения, выполняется ли код таким образом, или я пропускаю все после первого вызова transform.Translate.Объект перемещается в эту первую точку и далее, и дальше, и дальше ... Также то же самое, когда я выбираю другую из этих точек в качестве первого перевода.Я надеюсь, что кто-то может мне помочь.

1 Ответ

0 голосов
/ 03 июня 2019

Здесь много чего происходит.

Если у ваших transPointFirst, transPointSecond и т. Д. Есть какие-либо родительские игровые объекты, сравнение их localPosition с position из target может привести к неожиданному поведению.Вероятно, лучше сравнить их position поля напрямую.Кроме того, если их Z-компоненты их позиций уже 0, вам не нужно создавать дубликаты Vector3 из них.

Translate ожидает вектор направления, умноженный на расстояние, но выдают ему то, что кажется вектором позиции.Возможно, вы захотите использовать Vector3.MoveTowards для вычисления позиции target каждого кадра.Вам понадобится переменная, чтобы установить скорость, с которой вы хотите двигаться, в идеале это было бы открытое поле, поэтому вы можете установить его в инспекторе.

Кроме того, как сказал Эддж, вы делаете этосначала Translate при любых обстоятельствах, которые идут против логики, которую вы хотите.

Однако в Unity операторы Vector3 == и != уже проверяют приблизительное равенство, так что у вас все хорошо.

Вам также необходимо учитывать, что происходит с кадрами, когда объект находится между двумя позициями.Если вы вызываете ElevateCaptain на каждом кадре, когда он должен двигаться, вы можете проверить, находится ли его текущая позиция между каждой последовательной парой точек, или иметь некоторые переменные, которые отслеживают, к каким точкам он «прикоснулся», такдалеко.

Более простым способом написать то, что вы хотите сделать здесь, может быть использование Coroutine s , затем вызывать ElevateCaptain только один раз, когда вы хотите, чтобы оно начало двигаться.Вот пример того, как ваш код может выглядеть с этими изменениями и использованием сопрограмм:

public float elevateSpeed;
private bool captainElevating;

Start() 
{
    // ...
    captainElevating = false; 
    // ...
}

private void ElevateCaptain()
{
    if (!captainElevating) 
    {
        captainElevating = true;
        StartCoroutine("ElevateCaptainCoroutine");
    }
}

private IEnumerator ElevateCaptainCoroutine() 
{
    targetRigid.isKinematic = true

    while (target.transform.position != transPointFirst.position)
    {
        target.transform.position = Vector3.MoveTowards(
                target.transform.position,   
                transPointFirst.position,
                elevateSpeed * Time.deltaTime);
        yield return null;
    }

    while (target.transform.position != transPointSecond.position)
    {
        target.transform.position = Vector3.MoveTowards(
                target.transform.position,   
                transPointSecond.position,
                elevateSpeed * Time.deltaTime);
        yield return null;
    }

    while (target.transform.position != transPointThird.position)
    {
        target.transform.position = Vector3.MoveTowards(
                target.transform.position,   
                transPointThird.position,
                elevateSpeed * Time.deltaTime);
        yield return null;
    }

    while (target.transform.position != transPointFourth.position)
    {
        target.transform.position = Vector3.MoveTowards(
                target.transform.position,   
                transPointFourth.position,
                elevateSpeed * Time.deltaTime);
        yield return null;
    }

    targetRigid.isKinematic = false;
    captainElevating = false;
}

Если вы решите пойти по маршруту Coroutine, вы должны попытаться вызвать ElevateCaptain только один раз, когда захотитецель начинает движение, хотя включение переменной captainElevating не должно вызывать ее, пока она уже происходит.

Сопрограмма или иное, улучшение в этом может заключаться в использовании List из GameObject и иметь цикл Coroutine над списком, перемещая target к каждому по очереди.Таким образом, в инспекторе вы можете перетащить столько transPoint GameObjects, сколько захотите, в список и очень легко изменить его.Повторяющаяся структура подхода сопрограммы очень хорошо подходит для такой петли.

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