Почему WaitForSeconds вызывает изменение моего спрайта? - PullRequest
0 голосов
/ 30 января 2020

В моей игре я играю анимацию, жду окончания анимации, а затем меняю изображение спрайта. Затем я исчезаю из спрайта, жду окончания исчезновения, затем отключаю gameObject. Вот код:

IEnumerator UnlockSequence()
{
    anim.Play("unlock");
    unlocking = false; // stops UnlockSequence from being called again
    yield return new WaitForSeconds(1.7f);

    sr.sprite = sprite1; //change sprite

    StartCoroutine(FadeTo(0.0f, 2.0f)); 
    yield return new WaitForSeconds(2f);

    gameObject.SetActive(false);
}

IEnumerator FadeTo(float aValue, float aTime)
{
    float alpha = sr.color.a;
    for (float t = 0.0f; t < 1.0f; t += Time.deltaTime / aTime)
    {
        Color newColor = new Color(sr.color.r, sr.color.g, sr.color.b, Mathf.Lerp(alpha, aValue, t));
        sr.color = newColor;
        yield return null;
    }
}

Это прекрасно работает, за исключением случаев, когда я получаю yield return new WaitForSeconds(2f);, изображение спрайта возвращается к тому, которое было изначально, до анимации. Я понятия не имею, почему это происходит. Я знаю, что sr.sprite = sprite1; работает, потому что, когда я вынимаю yield return new WaitForSeconds(2f);, спрайт правильный. Любая помощь, чтобы исправить это будет принята с благодарностью.

РЕДАКТИРОВАТЬ:

Вот гиф проблемы, извините за ее ужасное качество, но, надеюсь, вы можете увидеть проблему.

проблема

Ответы [ 2 ]

2 голосов
/ 30 января 2020

Определенно не WaitForSeconds изменяет спрайт, а ваш Animator!

Причина

Если где-то в любом из AnimatorState у вас есть только один один ключевой кадр для определенного свойства (как, например, в вашем случае Sprite) Animator получает полный контроль над этим свойством, и вы можете не перезаписывать его с помощью сценария !

Далее у AnimatorState есть опция Write Defaults, о которой UnityTechnologies сказала в этой теме

В версии 5.0 мы добавили свойство в State к Write back default values , Это означает, что если он включен, он будет записывать значения по умолчанию всех анимированных свойств (на широком уровне контроллера), которые не анимированы в этом состоянии.

По умолчанию он включен, поэтому мы не меняем поведение, которое у нас было раньше.

Поэтому, если вы хотите, чтобы неанимированные свойства State имели значение оставьте значение , которое было ранее, просто выключите его .

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

One Solution

Так что если вы хотите, чтобы ваше состояние Default не перезаписывало Sprite поскольку в этом состоянии ключевой кадр для Sprite отсутствует, просто включите эту опцию.


Pure Animator Solution

Однако, я думаю, вы можете настроить Animator в как он может на самом деле обрабатывать все это без необходимости вашего сценария е xcept для запуска анимации один раз.

Вы говорите, что ваша установка Animator выглядит как

Вход → По умолчанию ← Разблокировать

Поэтому позвольте мне спросить:

  1. Почему бы просто не удалить этот переход обратно к Default? Это заставит его оставаться в состоянии unlock, пока вы не скажете иначе. При включении Loop Time, как у вас уже есть, это означает, что он остается на последнем ключевом кадре и в любом случае не вернется к значениям по умолчанию.

  2. Почему бы просто не включить затухание в вашу unlock анимацию? Просто установите ключевые кадры для свойства color. Таким образом, вам не нужно будет использовать скрипт для этого.

  3. В качестве альтернативы, если вы хотите управлять замиранием независимо от (не) блокировки, вы можете использовать несколько слоев анимации ! На основном слое вы делаете (не) блокировку. На другом слое вы делаете Fading с помощью свойства Color.

В общем, я обычно рекомендую настройку Animator, используя bool Параметры анимации для переходов , Затем, используя несколько слоев, он может выглядеть как

parameters 
   Bool "Open"
   Bool "FadeOut"

layers
    Base Layer

    Entry       -------------------> StateClosed
    StateClosed --(if Open==true)--> AnimOpening
    AnimOpening --(Exit time 1)----> StateOpen
    StateOpen   --(if Open==false)-> AnimClosing
    AnimClosing --(Exit time 1)----> StateClosed

    FadeingLayer (make sure to set Weight to `1` -  its `0` by default)

    Entry          -----------------------> StateFadedIn
    StateFadedIn   --(if FadeOut==true)---> AnimFadingOut
    AnimFaidingOut --(Exit time 1)--------> StateFadedOut
    StateFadedOut  --(if FadeOut==false)--> AnimFadingIn
    AnimFadingIn   --(Exit time 1)--------> StateFadedIn

Если вы хотите go, обязательно установите ключевые кадры для всех соответствующих свойств во всех состояниях, включая состояния одного ключевого кадра. То есть, например, в FadingLayer вы устанавливаете

StateFadedIn: Color.a = 1
StateFadedOut: Color.a = 0
AnimFadingOut: Color.a = well your keyframes here ;)
AnimFadingIn: Color.a = well your keyframes here ;)

и BaseLayer одинаково.

Таким образом, Animator не может испортить его при принудительном переходе между состояниями через скрипт.

А затем в коде достаточно просто установить

anim.SetBool("Open", true);

, а затем

anim.SetBool("FadeOut", true);

Наконец, вместо последнего вызова сценария вы можете улучшить эту настройку Анимация События , которые автоматически вызывают изменение FadeOut по завершении. После этого вы все равно можете управлять им с помощью скрипта, но вам не придется «вручную» ждать, пока анимация разблокировки не будет выполнена, прежде чем начинать затухание.


Я знаю, что это много информации, но я надеюсь, идея прояснится, и вы сможете разобраться с документацией;)

0 голосов
/ 30 января 2020

Трудно сказать, не видя анимацию, однако моя теория состояла бы в том, что ваша анимация зацикливается или заставляет спрайт восстановить исходный спрайт. Animator копирует свойства GameObject в зависимости от состояния, в котором они находились на временной шкале, когда были созданы ключевые кадры. Я только что скопировал ваш код, все работает как положено (подождите 1,5 секунды, изменяет спрайт, исчезает через 2,0 секунды и go неактивен). Единственное, чего у меня не было, это анимационный клип, который вы используете. Когда у меня есть немного времени позже, я могу проверить, добавив анимацию, но я бы посмотрел на это. Если бы вы могли поделиться скриншотом AnimationClip, это было бы полезно.

...