Создание динамических объектов GameObject и совместное преобразование их позиций из данных JSON - PullRequest
1 голос
/ 18 апреля 2019

Рассмотрим этот набор данных:

[
   {
     PartId: 0,
     Positions: [
       { x: 0, y: 0, z: 0, timeCode: 0.0000 },
       { x: 0, y: 0, z: 1, timeCode: 0.0025 },
       { x: 0, y: 0, z: 2, timeCode: 0.0050 },
       { x: 0, y: 0, z: 3, timeCode: 0.0075 },
       { x: 0, y: 0, z: 4, timeCode: 0.0100 },
       { x: 0, y: 0, z: 5, timeCode: 0.0125 },
       { x: 0, y: 0, z: 6, timeCode: 0.0150 },
       { x: 0, y: 0, z: 7, timeCode: 0.0175 },
       { x: 0, y: 0, z: 8, timeCode: 0.0200 },
     ]
   },
   {
     PartId: 1,
     Positions: [
       { x: 0, y: 0, z: 0, timeCode: 0.0000 },
       { x: 0, y: 0, z: 2, timeCode: 0.0025 },
       { x: 0, y: 0, z: 4, timeCode: 0.0050 },
       { x: 0, y: 0, z: 6, timeCode: 0.0075 },
       { x: 0, y: 0, z: 8, timeCode: 0.0100 },
       { x: 0, y: 0, z: 10, timeCode: 0.0125 },
       { x: 0, y: 0, z: 12, timeCode: 0.0150 },
       { x: 0, y: 0, z: 14, timeCode: 0.0175 },
       { x: 0, y: 0, z: 16, timeCode: 0.0200 },
     ]
   }
 ]

Я могу загружать и анализировать данные JSON, и я могу создать новый GameObject для каждого PartId. Я пытаюсь найти лучший способ преобразовать каждую «Часть» в соответствии с коллекцией Позиции одновременно.

У меня есть пустой GameObject в сцене с прикрепленным классом. Внутри метода Start я получаю данные JSON, а затем в цикле создаю класс GameObject, устанавливаю его начальную позицию и затем запускаю сопрограмму, определенную в том же классе.

Основной класс:

void Start() {
    // do json stuff...
    // ........
    // then
    // for each part...

    foreach(PartGroup pg in Parts) {
        // create a new GameObject from the Part class
        Part part = gameObject.AddComponent(typeof(Part)) as Part;
        // send this part data to the new GameObject
        part.PartGroup = pg;
        // set the initial position for the part
        part.Init();

        // start a IEnumerator Coroutine in the part class
        StartCoroutine(part.PlayFrom());
    }
}

Класс детали:

public void Init() {
    Joint = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    Joint.transform.localScale = new Vector3(jointSize, jointSize, jointSize);
    Joint.transform.position = new Vector3(PartGroup.Positions[0].X, PartGroup.Positions[0].Z, PartGroup.Positions[0].Y);
}
public IEnumerator PlayFrom(float time = 0f) {
    while (PlayBack(time)) {
        yield return null;

        time += Time.fixedDeltaTime;
    }
}
bool PlayBack(float time) {
    float sample = time / (Time.fixedDeltaTime / speed);
    int previousIndex = (int)(sample);
    int last = PartGroup.Positions.Count - 1;

    if (previousIndex < last) {
        int nextIndex = previousIndex + 1;
        float interpolation = sample - previousIndex;

        Joint.transform.position = Vector3.Lerp(
            new Vector3(PartGroup.Positions[previousIndex].X, PartGroup.Positions[previousIndex].Z, PartGroup.Positions[previousIndex].Y),
            new Vector3(PartGroup.Positions[nextIndex].X, PartGroup.Positions[nextIndex].Z, PartGroup.Positions[nextIndex].Y),
            interpolation);

        return true;
    }
    Joint.transform.position = new Vector3(PartGroup.Positions[last].X, PartGroup.Positions[last].Z, PartGroup.Positions[last].Y);

    return false;
}

Вот так у меня сейчас настроено. Это работает, но это не плавное движение, и иногда кажется, что оно запаздывает или перепрыгивает кадры. Это лучший способ сделать это, или есть лучший способ (например, FixedUpdate)? Я установил свойство фиксированного времени в настройках своего проекта в соответствии с временным кодом данных.

Любая помощь с лучшими практиками для подобных вещей очень ценится!

1 Ответ

2 голосов
/ 18 апреля 2019

Вы должны использовать Time.deltaTime в

time += Time.deltaTime;

и

float sample = time / (Time.deltaTime / speed);

Сопрограммы выполняются вместе со всеми Update вызывает так, что использование fixedDeltaTime нарушает независимость фрейма.

или, возможно, использует WaitForFixedUpdate для его выполнения, например FixedUpdate

while (PlayBack(time)) {
    yield return new WaitForFixedUpdate();

    time += Time.fixedDeltaTime;
}

Также в

foreach(PartGroup pg in Parts) 
{
    // create a new GameObject from the Part class
    Part part = gameObject.AddComponent(typeof(Part)) as Part;
    // send this part data to the new GameObject
    part.PartGroup = pg;
    // set the initial position for the part
    part.Init();

    // start a IEnumerator Coroutine in the part class
    StartCoroutine(part.PlayFrom());
}

похоже, что вы добавляете компонент для каждого элемента в списке к одному и тому же GameObject .. Я не знаю, если это то, что выпланировал сделать.AddComponent не создает новый GameObject с этим компонентом, но присоединяет этот компонент к тому же gameObject, к которому присоединен скрипт.

Возможно, вы используете new GameObject

Part part = new GameObject("new GameObject").AddComponent<Part>();
// make it a child of this gameObject?
part.SetParent(gameObject, false);

также расчеты

float sample = time / (Time.fixedDeltaTime / speed);
int previousIndex = (int)(sample);

...

float interpolation = sample - previousIndex;

кажутся немного странными ... Вы уверены, что он всегда возвращает значение между 0 и 1?

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