Animation Duration

Announcements, support questions, and discussion for the Dialogue System.
pegassy
Posts: 135
Joined: Sat Mar 17, 2018 8:07 pm

Re: Animation Duration

Post by pegassy »

Thank you for clarifying. I see many possible tools in documentation while I am reviewing it, but it does not appear to me to use those at a specific situation until you remind me. Thank you for your patience.
User avatar
Tony Li
Posts: 22057
Joined: Thu Jul 18, 2013 1:27 pm

Re: Animation Duration

Post by Tony Li »

My friend, even I sometimes forget little features that are available in the Dialogue System. :-) Every feature is fairly well considered; I try to avoid unnecessary fluff. But when you get down to making truly AAA-polished dialogue, it's sometimes surprising how many little details it takes.
pegassy
Posts: 135
Joined: Sat Mar 17, 2018 8:07 pm

Re: Animation Duration

Post by pegassy »

Tony Li wrote: Sat Dec 15, 2018 8:26 pm subject.GetComponent<Animator>().CrossFade("Idle", 0.5f); // ...cross fade to Idle.[/code]
assumes that you want to play the animator state named "Idle". And of course it assumes that it should start crossfading into that state in the last 0.5 seconds.
Hello Tony,

I have been playing around with the modified LipTalk script. It does seem to do a good job making a transition back to idle for every LipTalk( ) command. However, it does not seem to end the original conversation animation. It is a long animation (16 seconds) and will continue to run even after the conversation is over.

If I add Required AnimatorPlay(Idle)@{{end}} (or a specified number of seconds) by the end of every single node's sequence commands, then that does stop the conversation animation, but rather abruptly, and will not look nice. I was playing around with the transitions between the conversation animation and idle in the animator, and that does not seem to make any difference.

Do you have any hints on how to use DSU to transition smoothly between these two animations?

Thank you.
User avatar
Tony Li
Posts: 22057
Joined: Thu Jul 18, 2013 1:27 pm

Re: Animation Duration

Post by Tony Li »

You probably need to change something in the animator controller. Are "Idle" and "Talk" on the same layer? Are there any transition arrows in that layer? (If possible, please post a screenshot.)

I made the assumption that your animator controller's base layer looks something like this:
idleTalk.png
idleTalk.png (6.42 KiB) Viewed 842 times
Specifically, there are no transition arrows leading into the Talk state.

In your current case, does the animator transition to Idle and then return to Talk?
pegassy
Posts: 135
Joined: Sat Mar 17, 2018 8:07 pm

Re: Animation Duration

Post by pegassy »

Both idle and talk are in the same layer (there is a single layer for that character) The animator controller for that character looks like the attached photo.

I tried to delete the transition from Conv2 to Idle with the same result. I was not sure if the transition was being controlled by the DSU script or the Unity's state machine.

Here is the sequence code inside the particular conversation node:

LipTalk(TS_7);AnimatorPlay(Conv2, Sastig); Required AnimatorPlay(Idle)@3

Sorry for the lack of sufficient information in the first post. Thank you for your help.
Attachments
2018-12-22-Animation Transitions.png
2018-12-22-Animation Transitions.png (8.36 KiB) Viewed 841 times
User avatar
Tony Li
Posts: 22057
Joined: Thu Jul 18, 2013 1:27 pm

Re: Animation Duration

Post by Tony Li »

Let's break it down:

Code: Select all

LipTalk(TS_7);
^ This tells the speaker's LipSync component to play TS_7. At 0.5 seconds before the end, it tells the speaker's Animator to crossfade to Idle.

Since the last time I posted SequencerCommandLipTalk.cs, you mentioned that it didn't crossfade to idle if the player skips ahead. Here's an updated version that should guarantee that it crossfades to idle even if the player skips ahead:
SequencerCommandLipTalk.cs

Code: Select all

using System.Collections;
using UnityEngine;
using RogoDigital.Lipsync;

namespace PixelCrushers.DialogueSystem.SequencerCommands
{

    public class SequencerCommandLipTalk : SequencerCommand
    {

        private LipSync lipSync = null;
        private AudioClip audioClip = null;
        private bool nowait = false;
        private bool hasGoneToIdle = false;

        public IEnumerator Start()
        {
            var lipSyncAssetName = GetParameter(0);
            var lipSyncData = DialogueManager.LoadAsset(lipSyncAssetName, typeof(LipSyncData)) as LipSyncData;
            var subject = GetSubject(1, Sequencer.Speaker);
            lipSync = (subject == null) ? null : subject.GetComponentInChildren<LipSync>();
            nowait = string.Equals(GetParameter(2), "nowait", System.StringComparison.OrdinalIgnoreCase);
            if (lipSync == null)
            {
                if (DialogueDebug.LogWarnings) Debug.LogWarning("Dialogue System: Sequencer: LipSync(" + GetParameters() + "): LipSync subject not found");
                Stop();
            }
            else if (lipSyncData == null)
            {
                if (DialogueDebug.LogWarnings) Debug.LogWarning("Dialogue System: Sequencer: LipSync(" + GetParameters() + "): LipSync Data not found");
                Stop();
            }
            else
            {
                if (DialogueDebug.LogInfo) Debug.Log("Dialogue System: Sequencer: LipSync(" + lipSyncData + ", " + lipSync + (nowait ? ", nowait" : string.Empty) + ")");
                lipSync.Play(lipSyncData);
                audioClip = lipSyncData.clip;
                if (nowait) Stop();
                yield return new WaitForSeconds(audioClip.length - 0.5f); // 0.5 seconds before the end...
                subject.GetComponent<Animator>().CrossFade("Idle", 0.5f); // ...cross fade to Idle.                
                hasGoneToIdle = true;
            }
        }

        public void Update()
        {
            if (DialogueTime.IsPaused)
            {
                if (!lipSync.IsPaused) lipSync.Pause();
            }
            else
            {
                if (lipSync.IsPaused) lipSync.Resume();
                if (!lipSync.IsPlaying)
                {
                    Stop();
                }
            }
        }

        public void OnDestroy()
        {
            if (lipSync == null) return;
            if (nowait) return; // If nowait, don't manually stop.
            if (lipSync.audioSource != null && lipSync.audioSource.clip != audioClip) return; // If already playing a different clip, don't stop it.
            lipSync.Stop(true);
            if (!hasGoneToIdle) lipSync.GetComponent<Animator>().CrossFade("Idle", 0.5f); // Cross fade to Idle.
        }

        //// If you want to debug LipSync, uncomment the method below:
        //private void OnGUI()
        //{
        //    if (lipSync.IsPlaying) GUILayout.Label("LipSync.IsPlaying");
        //    if (lipSync.IsPaused) GUILayout.Label("LipSync.IsPaused");
        //}
    }
}

Code: Select all

AnimatorPlay(Conv2, Sastig);
^ This tells the Animator on the GameObject named "Sastig" to play the state Conv2.

Is Sastig a different GameObject, such as the other conversation participant? If the animator controller screenshot is for Sastig, presumably when Conv2 finishes it will automatically transition to Idle.

Code: Select all

Required AnimatorPlay(Idle)@3
^ At the 3-second mark, this tells the speaker's Animator to play the Idle state.

Maybe the updated LipTalk script above will address the issue.

If not, please open an Animator window on the speaker and let me know what state it's in when the lipsync is done.

Also, are there any warnings in the Console window?

If you prefer to send a copy of your project to tony (at) pixelcrushers.com, I can take a look and hopefully reply with a solution.
pegassy
Posts: 135
Joined: Sat Mar 17, 2018 8:07 pm

Re: Animation Duration

Post by pegassy »

I appreciate the walkthrough and the update in the script. The update does seem to work. It is cancelling the previous animation 0.5 seconds before the end of the node. So I do not need to type in to play the idle before the end of every node.

For the transition issue, I think I may have some misconceptions about Unity's animation transitions, and may have false expectations about what I should see when there is a crossfade from the conversation animation to idle animation. Because from what I can see in the video that shared in the attachment, the animator controller does seem to be having the crossfade between the two, but I still see an abrupt jump from the middle of the conversation animation to the idle animation. I will go back to do more testing on a new project and do a bit more tutorial digging to avoid wasting your time on that regard. Somehow I have the notion that a smooth blend should happen between the two animations during that transition, but maybe I really need to set up an animation blend to do that.

Thank you tons for all the help.
Attachments
2018-12-23 20-12-03.rar
(160.31 KiB) Downloaded 67 times
pegassy
Posts: 135
Joined: Sat Mar 17, 2018 8:07 pm

Re: Animation Duration

Post by pegassy »

Never mind my previous post. It is working! I forgot the liptalk idle sequencer code in one of the nodes and that was causing the abrupt change. When I took it out, just with the modified liptalk code, it is working great. The conversation animation smoothly blends back into the idle animation. It looks great!

Just one question: so the animation transition begins 0.5 seconds before the end of the node. So if I want to change how long the crossfade is taking, should I change the float value in the following line?

subject.GetComponent<Animator>().CrossFade("Idle", 0.5f); // ...cross fade to Idle.

Currently the crossfade seems to be taking several seconds. That is, the time that both animations seem to be running is as long. Do I understand it right?
User avatar
Tony Li
Posts: 22057
Joined: Thu Jul 18, 2013 1:27 pm

Re: Animation Duration

Post by Tony Li »

To change the time that the crossfade starts, change the "0.5" in these two lines in Start():

Code: Select all

                yield return new WaitForSeconds(audioClip.length - 0.5f); // 0.5 seconds before the end...
                subject.GetComponent<Animator>().CrossFade("Idle", 0.5f); // ...cross fade to Idle.                
and this line is OnDestroy():

Code: Select all

            if (!hasGoneToIdle) lipSync.GetComponent<Animator>().CrossFade("Idle", 0.5f); // Cross fade to Idle.
If it's not cross-fading as fast as you want, inspect the transition in the Animator window. Make sure Has Exit Time is unticked. There's also a graphical representation of the fade. Try adjusting the sliders to make the blue transition area bigger or smaller.
pegassy
Posts: 135
Joined: Sat Mar 17, 2018 8:07 pm

Re: Animation Duration

Post by pegassy »

Thank you so much Tony.
Post Reply