Лучший способ плавно переместить мой Gameobject?

У меня проблема, когда я пытаюсь плавно переместить игровой объект.

Я получаю каждую секунду по протоколу TCP позицию, в которую должен переместиться мой Gameobject. Итак, у меня есть начальная позиция, моя конечная позиция, я могу рассчитать расстояние между двумя позициями, и я знаю, что мой Gameobject должен переместиться. с постоянной скоростью до моей конечной точки за 1 секунду.

Я пробую 3 решения: Learp, MoveToward и SmoothDamp, но ни одно из них не работает, мой Gameobject просто телепортируется из точки A в точку B. каждый раз.

Вот что я пробую в своем коде (мой Gameobject упоминается в словаре, мой Gameobject - это самолеты):

// Distance between my 2 points
float step = Vector3.Distance(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y));
//Use of Lerp
//planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.Lerp(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), step);
//Use of MoveTowards
planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.MoveTowards(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), step);
//Use of SmoothDamp
//planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.SmoothDamp(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), ref newPlane.GroundSpeed, 1);

Код - это функция, которая вызывается в моем обновлении следующим образом:

void Update () {
        lock (threadLock)
        {
            // Message receive from my TCP Protocol
            while (q_orders.Count > 0)
            {
                switch (q_orders.Dequeue())
                {
                    case OrderType.trackmovedevent:
                        aircraftMajInfos(q_args.Dequeue()); // My function to move my Object
                        break;
                }
            }
        }
    }

person Evans Belloeil    schedule 14.04.2016    source источник
comment
вы вызываете MoveTowards в Update () или в любом другом цикле?   -  person Uri Popov    schedule 14.04.2016
comment
Да, звоню в своем Апдейте.   -  person Evans Belloeil    schedule 14.04.2016
comment
используйте более низкие значения для последнего аргумента для Lerp и SmoothDamp. Lerp работает так: он берет точку A и точку B, затем смотрит на значение S в последнем параметре и возвращает точку C. В основном S представляет собой нормализованное значение между A и B, то есть S = 0 возвращает A, S = 1 возвращает B , S = 0,5 возвращает среднюю точку между A и B и так далее ... Другими словами, отношение Distance (A, C) и Distance (B, C) равно отношению S и (1 - S). Таким образом, в вашем случае создание S 1 всегда будет возвращать точку назначения, что приведет к телепорту. Сделайте это значение меньше 1.   -  person Nika Kasradze    schedule 14.04.2016
comment
Кроме того, чтобы сделать Lerp независимым от частоты кадров, можно просто умножить значение S на Time.deltaTime. Так что у парня, играющего со скоростью 60 кадров в секунду, не будет более быстрых переходов, чем у парня, играющего на 30 кадрах в секунду.   -  person Nika Kasradze    schedule 14.04.2016
comment
С помощью этого решения, как я могу быть уверен, что перейду от точки A к точке B за 1 секунду? Я пытаюсь поставить третий параметр на 0.1 * Time.deltaTime, и он движется очень медленно и не плавно :(   -  person Evans Belloeil    schedule 14.04.2016
comment
о нет, если вы умножите на Time.deltaTime, вы также можете увеличить S, потому что Time.deltaTime равен 1 / FPS, что очень мало. Попробуйте 10 * Time.deltaTime или что-то в этом роде.   -  person Nika Kasradze    schedule 14.04.2016


Ответы (3)


Лучше использовать движок промежуточного кадра, например http://dotween.demigiant.com/.

Если вы установите Dotween, вы можете просто использовать

transform.DOMove(new vector3(1 ,0 , 1) , duration);

Вы также можете установить «Легкость» для подростков. или используйте Oncomplete fucntions;

transform.DOMove(new vector3(1 ,0 , 1) , duration)
    .SetEase(Ease.OutCubic)
    .OnCompelete(() => { shouldClose = true; }); 
person AminSojoudi    schedule 14.04.2016
comment
Ого, это чистый чувак! Разрешите все мои проблемы с рамками! Но я не уверен, что скорость постоянна, похоже, нет, между каждой точкой есть ускорение и замедление. - person Evans Belloeil; 14.04.2016
comment
вы можете установить для Ease type значение Linear - person AminSojoudi; 14.04.2016

Я должен сказать, что вы совершенно неправильно поняли все три функции. Их следует вызывать в нескольких обновлениях, а не один раз.

В этой ситуации я рекомендую MoveTowards. Поскольку SmoothDamp не перемещает объект с постоянной скоростью, и для использования Lerp вам необходимо вычислить соотношение между двумя точками (обратите внимание, что вы МОЖЕТЕ перемещать объект постоянно, если вы добавляете величину к параметру t при каждом фиксированном обновлении) .

Вот фрагмент кода, который я написал для MonoBehaviour вашего игрового объекта.

const float moveTime = 1;
Vector3 target, step;

void Update () {
    transform.position = Vector3.MoveTowards(transform.position, target,
        step / moveTime * Time.deltaTime);
}
// Call this method to set the new target (the currently received position from network)
public void SetTarget (Vector3 positon) {
    target =  positon;
    step = Vector3.Distance(transform.position, target);
}

Time.deltaTime - интервал между обновлениями (где вызывается функция Update ())

person DRKblade    schedule 14.04.2016
comment
Хорошо, теперь я понимаю, почему мой объект телепортируется, потому что я вызываю его только один раз, когда мне нужно вызывать его несколько раз, спасибо, но для вызова моей функции я использую логическое значение в моем обновлении, поэтому у меня нет другого решение, чем вызов его в течение всего 1 кадра, есть ли способ выполнить MoveTowards? Если непонятно, обновлю свой код. - person Evans Belloeil; 14.04.2016
comment
@EvansBelloeil Итак, вы нашли решение проблемы; но в следующий раз, когда вы зададите вопрос, не забудьте обрезать слишком длинные строки кода, эти коды очень трудно читать. - person DRKblade; 14.04.2016

Я бы посоветовал следующее:

  • Создайте новый скрипт «ObjectMover» (возможно, не лучшее название) и примените его к игровым объектам, которые вы хотите перемещать.
  • В сценарии создайте общедоступный метод: MoveToNewPos (Vector3 newPos), который сохраняет новую позицию, к которой вы стремитесь с помощью этого объекта.

Внутри метода обновления «ObjectMover» используйте lerp или вычислите шаг самостоятельно, используя step / moveTime * Time.deltaTime, чтобы перейти к желаемой новой позиции и настроить только скорость в соответствии с желаемым внешним видом.

Из вашего «основного» скрипта выполните theObjectIWantToMove.GetComponent (). MoveToNewPos (newPos); и он будет плавно туда двигаться.

person Mikael Larsson    schedule 14.04.2016