Я не знаю, как выглядят ваши анимационные клипы и как выглядят ваши переходы, но вот несколько советов:
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
, чтобы позволить обрабатывать только одно нажатие клавиши одновременно.
Для простогодверь только с двумя состояниями и без сложных анимаций между ними, я бы предложил другой подход:
Не экспортируйте анимации из Blender только для модели
Для вращающейся двери убедитесь, что шарнир находится на оси, которую вы хотите вращать вокруг
В аниматоре есть только два состояния, например Opened
|Closed
Вместо триггеров используйте bool, например: IsOpen
Создайте свои "анимации" так, чтобы оба имели только точно1
ключевой кадр и отключить Loop Time
в инспекторе.Unity интерполирует между двумя анимациями автоматически, поэтому, если в анимации имеется только один ключевой кадр, вся интерполяция между значениями (позициями, цветами, поворотами и т. Д.) Автоматически обрабатывается самим Unity.
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 ключевым кадром