#animation event

1 messages · Page 1 of 1 (latest)

humble ridge
#

sure

normal field
#

Oh wow, thanks man, I'll go get my laptop soz

humble ridge
#

just a note, still in a dungeon rn, might take a minute xD

radiant thunder
#

i do have a coroutine version with a CustomYieldInstruction for (what i think) you want

#

for "wait until the animator finishes playing the current state"

#
using UnityEngine;

class AnimatorPlaying : CustomYieldInstruction {
    Animator animator;

    const int startBufferFrames = 2;

    public override bool keepWaiting {
        get {
            if (bufferFrames > 0) {
                bufferFrames--;
                return true;
            } else {
                return animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1;
            }
        }
    }

    private int bufferFrames;

    public AnimatorPlaying(Animator animator) {
        this.animator = animator;
        bufferFrames = startBufferFrames;
    }
}
normal field
#

Ok so this is basically what I tried doing, if this makes any sense.

I tried to make the transitioning more general this way, instead of my specific use case

#

Like this is for animations in other levels, whereas in level 1, it's basically only transitioning between the Talking and Waiting states

#

This is how it worked in my first level, just basic transitions

#

The events being fired based on signal emitters in unity timeline

azure basinBOT
normal field
#

Ah ok, sorry, thought screenshots would be fine

#
using Cysharp.Threading.Tasks;
using UnityEngine;

public class AnimationController : MonoBehaviour
{
    public Animator anim;
    private void Awake()
    {
        anim = GetComponent<Animator>();
        GameState.decisionTime += PlayerSpeaking;
        GameState.distributeDecision += _ => NPCSpeaking();
        GameState.verdictTime += PlayerSpeaking;
       
    }

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    

    public  virtual void NPCSpeaking()
    {
        anim.SetTrigger("NPC_Speaking");
    }

    public void PlayerSpeaking()
    {
        anim.SetTrigger("Player_Speaking");
    }

    //public async UniTask StateTransition(string stateName, string triggerName)
    //{
    //    anim.SetTrigger(triggerName);
    //    while (!anim.GetCurrentAnimatorStateInfo(0).IsName(stateName))
    //    {
    //        await UniTask.Yield();
    //    }
    //}

    protected void OnDestroy()
    {
        GameState.decisionTime -= PlayerSpeaking;
        GameState.distributeDecision -= _ => NPCSpeaking();
        GameState.verdictTime -= PlayerSpeaking;
        
    }
}
humble ridge
#

Mhh and what part of that is giving you trouble now?

#

I understand what you are trying to do, but not what part of it you are having trouble with

normal field
# humble ridge I understand what you are trying to do, but not what part of it you are having t...

Well not that necessarily, it's more so how I can have that UniTask function react to an event that would start the transition if you get me, what I'm trying to do is:

React to progress bar filling:

  • Transition to an idle animation

  • Start silencing the audio, using an audiomixer snapshot.

  • Wait for the NPC to transitioning to a different animation.

  • Restore the normal audio, using an audiomixer snapshot.

  • Play the other timeline sequence to complete the transition

does this make sense?

normal field
#

@humble ridge

Ok this is what I came up with for this:


public class Level2Timelines : TimeLineController {

{...}

protected override void Awake() {
metreManager.TriggerInterruption += (interruptType) => PlayInterrupt(interruptType)

{...}
}

protected void PlayInterrupt(string interruptType) {

{...}
//I want to fire and forget this in PlayInterrupt to carry out the event, but still await it inside itself to complete the transition.
_ = interruptionTransition

}
    protected async UniTaskVoid interruptionTransition()
    {
        
        Debug.Log("Starting silence transition");
        _ = level2Animations.InterruptedAnimation();
        _ = audioMixerControl.SilenceTransition();


        await UniTask.WaitUntil(() => level2Animations.GetCurrentState().IsName("Waiting")
        && audioMixerControl.getCurrentSnapshot() == audioMixerControl.silence);

        
        _ = level2Animations.IdleToArguing();
        _ =audioMixerControl.BackToNormal();
        await UniTask.WaitUntil(() => level2Animations.GetCurrentState().IsName("Arguing")
        && audioMixerControl.getCurrentSnapshot() == audioMixerControl.normal);

        activeInterrupt.Play();
    }

}


#
using Cysharp.Threading.Tasks;
using System;
using UnityEngine;

public class Level2Animation : AnimationController
{
    public event Action NPCTalking;


    public override void NPCSpeaking()
    {
        NPCTalking?.Invoke();
    }

    public AnimatorStateInfo GetCurrentState()
    {

        return anim.GetCurrentAnimatorStateInfo(0);
    }

    public async UniTaskVoid InterruptedAnimation()
    {
        anim.SetTrigger("Start_Interruption");
        await UniTask.Yield();
    }

    public async UniTaskVoid IdleToArguing()
    {
        anim.SetTrigger("NPC_Arguing");
        await UniTask.Yield();
    }

}

using UnityEngine;
using UnityEngine.Audio;
using Cysharp.Threading.Tasks;
public class AudioMixerControl : MonoBehaviour
{
    public AudioMixer gameAudio;

    public AudioMixerSnapshot normal;
    public AudioMixerSnapshot silence;
    protected AudioMixerSnapshot currentSnapshot;

    protected float transitionTime = 0.1f; 

    private void Awake()
    {
        normal = gameAudio.FindSnapshot("Normal");
        silence = gameAudio.FindSnapshot("Silence");
        currentSnapshot = normal;
    }

    public AudioMixerSnapshot getCurrentSnapshot()
    {
        return currentSnapshot;
    }

    public async UniTaskVoid SilenceTransition()
    {   
        
        silence.TransitionTo(transitionTime);
        currentSnapshot = silence;
        await UniTask.Yield();
    }

    public async UniTaskVoid BackToNormal()
    {
        normal.TransitionTo(transitionTime);
        currentSnapshot = normal;
        await UniTask.Yield();
    }

}

For more clarity

#

Sorry for the tag, just wanted to make sure you can see this but don't feel rushed to reply obvs

#

Also, the reason why I have hardcoded strings is because this is for a one-off use case

#

Pretty much my project is a prototype of a serious game I'd like to make

normal field
#

Also the reason I have those Yield statements, is because I wanted to fire and forget them in the first screenshot so that they start simultaneously, then I thought adding a frame buffer would be helpful in ensuring synchronisation.

Then after those two fire, we just wait until they result in the values we want.

Please correct me if I'm wrong.