Blender to Unity Animation - прыжки в кадрах - PullRequest
0 голосов
/ 14 декабря 2018

Я решил попробовать экспортировать модель Blender в FBX с анимацией в Unity.Есть две анимации, открытые и закрытые для верхней двери этой модели.Вот в чем дело - кажется, моя модель любит прыгать в начало ОБА анимаций, когда модель запущена, т.е.если я импортирую модель, и дверь открыта, и я решаю активировать, чтобы ЗАКРЫТЬ ее, она закроется должным образом - но затем, когда я пытаюсь ОТКРЫТЬ ее, она решает, что должна остаться в том же источнике, что и анимация закрывающейся двериво-первых, ТОГДА он открывается - в основном это приводит к тому, что дверь заходит слишком далеко за пределы модели.

Я также высказал мысль попробовать опираться на ОДНУ анимацию в элементе управления аниматором Mecanim - но, кажется, покаВернитесь в правильное место для двери при движении в противоположном направлении, она не делает это с той же скоростью, но делает это беспорядочно.Наконец, когда я пытаюсь сделать анимацию одной двери на ту же анимацию двери с противоположной скоростью (т. Е. Дверь рядом с дверью закрыта, одна со скоростью 1 и одна со -1), она все равно скачет беспорядочно.

Вот последняя настройка аниматора Mecanim, которую я пытался:

enter image description here

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

Я использую триггеры состояний для перехода между этими состояниями в приведенном ниже коде:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

public class TriggerAnimation : MonoBehaviour {

    public Transform cockPit;
    // Use this for initialization
    void Start () {


    }

    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown("t"))
        {
            //AnimationPlayableUtilities.PlayClip("CockPit_ExtDoor|Open");
            Debug.Log("I'm being pressed");
            //GetComponent<Animator>().SetTrigger("ExtDoorOpen");
            GetComponent<Animator>().SetTrigger("IntDoorOpen");
            //GetComponent<Animator>().SetTrigger("CockPit_Door|Open");

        }
        if (Input.GetKeyDown("u"))
        {
            //PlayableGraph graph = new PlayableGraph();
            //AnimationPlayableUtilities.PlayAnimatorController(GetComponent<Animator>(), GetComponent<RuntimeAnimatorController>(), out graph);
            Debug.Log("I'm being pressed");
            //GetComponent<Animator>().SetTrigger("ExtDoorClose");
            GetComponent<Animator>().SetTrigger("IntDoorClose");
            //GetComponent<Animator>().SetTrigger("CockPit_Door|Close");

        }
        if (Input.GetKeyDown("x"))
        {
            GetComponent<Animation>().Play("CockPit_IntDoor|Open");
        }
        if (Input.GetKeyDown("z"))
        {
            GetComponent<Animation>().Play("CockPit_IntDoor|Close");
        }
    }
}

Может кто-нибудь сообщить мне, если есть лучшеспособ подойти к этому и как?Я пробовал переходить между несколькими статьями по этому вопросу, включая демонстрационное руководство по Mecanim для Unity на их веб-сайте - без кубиков ...

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Я не знаю, как выглядят ваши анимационные клипы и как выглядят ваши переходы, но вот несколько советов:

if (Input.GetKeyDown("x"))
{
    GetComponent<Animation>().Play("CockPit_IntDoor|Open");
}

if (Input.GetKeyDown("z"))
{
    GetComponent<Animation>().Play("CockPit_IntDoor|Close");
}

Animator.Play напрямую «переходит» в целевое состояние без какого-либо перехода,Но анимация перезапускается каждый раз, когда вы нажимаете клавишу.

Triggers складываются, поэтому, если вы нажмете, например, несколько раз кнопку открытия, а затем нажмите кнопку закрытия, вы сделаете оба (или даже несколько) перехода междудва состояния, поскольку Trigger сбрасывается, только если он используется (или активно сбрасывается в сценарии с использованием Animator.ResetTrigger).

И еще одна проблема, которую я вижу, состоит в том, что в настоящее время вы используете разъединенные операторы if... так что теоретически можно нажимать все 4 клавиши одновременно, что может привести к некоторым проблемам (вызов Play будет непосредственно переходить в целевое состояние, но триггеры от вызовов до Settrigger будут все еще тами сложены так, что возможно, что ваш аниматор делает различные переходы от следующего кадра.) Вы, скорее, должны использовать операторы if-else, чтобы позволить обрабатывать только одно нажатие клавиши одновременно.


Для простогодверь только с двумя состояниями и без сложных анимаций между ними, я бы предложил другой подход:

  1. Не экспортируйте анимации из Blender только для модели

  2. Для вращающейся двери убедитесь, что шарнир находится на оси, которую вы хотите вращать вокруг

  3. В аниматоре есть только два состояния, например Opened |Closed

  4. Вместо триггеров используйте bool, например: IsOpen

  5. Создайте свои "анимации" так, чтобы оба имели только точно1 ключевой кадр и отключить Loop Time в инспекторе.Unity интерполирует между двумя анимациями автоматически, поэтому, если в анимации имеется только один ключевой кадр, вся интерполяция между значениями (позициями, цветами, поворотами и т. Д.) Автоматически обрабатывается самим Unity.

  6. MakeВаши переходы выполняются следующим образом

    • ExitTime -> 1
      На самом деле мы не будем использовать время выхода, но это исправляет небольшую ошибку, выдающую предупреждение

      Разница в эффективной длине между состояниями слишком велика.Предварительный просмотр перехода будет отключен.UnityEngine.GUIUtility: ProcessEvent (Int32, IntPtr)

      , если вы включите его 0

    • HasExittime -> false
      Это означает, что нене ждите, пока анимация закончится или в определенном кадре, чтобы сделать переход, но сделайте это немедленно (анимация с только ключевым кадром автоматически имеет длину по умолчанию 1 секунда)
    • FixedDuration -> true(мы хотим настроить вещи за считанные секунды)
    • TransitionDuration(s) -> Здесь вы теперь настраиваете, как долго вы хотите, чтобы переход занимал (он также может быть различным для открытия и закрытия)
    • TransitionOffset -> 0 (анимация имеет только 1 ключевой кадр, поэтому мы не хотим запускать его в другом кадре)

    • и, наконец, ваши два условия

      • Открыть -> Закрыть: условия: IsOpen == false
      • Закрыть -> Открыть: условия: IsOpen == true

Чем позже в коде вы вместо этого будете использовать

// Store the component frerence instead of getting it everytime again
private Animator _animator;

private void Awake()
{
    _animator = GetComponent<Animator>();
}

private void Update()
{
    if (Input.GetKeyDown("t"))
    {
        Debug.Log("t is being pressed");
        _animator.SetBool("IsOpen", true);
    }
    // use if-else in order to process only one of the buttons at a time
    else if (Input.GetKeyDown("u"))
    {
        Debug.Log("u is being pressed");
        _animator.SetBool("IsOpen", false);
    }
    // you still can keep those for jumping to a state directly without the transition
    else if (Input.GetKeyDown("x"))
    {
        _animator.Play("Opened");
    }
    else if (Input.GetKeyDown("z"))
    {
        _animator.Play("Closed");
    }
}

Теперь, используя значение Bool вместо триггеров, вам не нужно заботиться о стекезвонки.Я надеюсь, что этот подход к анимации с 1 ключевым кадром соответствует вашим требованиям.


Если вам требуется несколько «шагов» в процессе открытия и закрытия, например, из-за наличия сложной анимации разблокировки до того, как дверь фактически сдвинется, я бырекомендуем

  • использовать состояние для каждого шага
  • связать все в одном направлении с HasExitTime = true и ExitTime = 1
  • Используйте вышеупомянутую настройку для интерполяции междуэти состояния
  • И, наконец, есть два условия перехода между каждой «парой шагов» на пути, поэтому каждая анимация либо переходит в «более открытое» в IsOpen = true, либо в «более закрытое» в IsOpen = false

Для лучшего понимания, вот пример того, как более сложные настройки могут выглядеть только при использовании такой анимации с 1 ключевым кадром

enter image description here

0 голосов
/ 14 декабря 2018

У меня было много трудностей с приведением анимаций из блендера в единство.Здесь много подводных камней.Вот пара вещей, которые я бы попробовал.дайте мне знать, если что-то из этого работает для вас.

 When animating a model in blender it often happens that the origin of  your model
 has accidentally been moved or is not in the exact same place between your two animations
 and when that gets imported into unity it has a way of messing with your animations.
 So just double check between your animations and make sure that the origin has not 
 shifted between the two animations
  • Убедитесь, что вы не применяете RootMotion в аниматоре Unity

enter image description here

Документы для применения корневого движения здесь

 basically what it does if enabled is for any movement that takes place in your
 animation it adds whatever movement transpired in the animation to its current position
 Therefore if the root object of the door moved left by 2units when it opens and your are 
 applying root motion the object would then be 2 units left of where you would
 expect. And it would just continue to stack getting further and further left.

  • Убедитесь, что вы удалили все ключи transform.position, которые есть в анимационном клипе.
 I am assuming that you do not want to actually have the position of the door move but 
 instead just have the animation make it appear as if the door is moving. If so in that case
 Assuming that your object is setup right. Which in my mind if it was a sliding door it would
 have an object tree like this RootObject>Frame>Door. With that being the case the only 
 object that should have any animation keys on it should be the door object. the other parent
 objects should be stationary.


  • Незначительное предложение.Я бы использовал bool вместо триггера.Таким образом, было бы легче отслеживать состояние двери.(IE основывает вашу анимацию на "isClosed" bool)

Это всего лишь несколько полезных советов по устранению неполадок, которые я нашел полезными в прошлом.

...