Forum rules - please read before posting.

Custom Speech Tokens only call once per ActionList item--is there a workaround for this?

Hello again!

I'm currently working on a custom way to handle bust portraits without using the AC expressions system because I need more control over when the animations play/how the animations transition between each other. I want to use Mecanim and Animation Events for some expressions to have "intros" that happen when the expression is first called, but not a part of the main expression animation loop.

I thought I could accomplish this by establishing a custom speech event token that calls for an animator to play the animation I name, as shown below:

private string OnRequestSpeechTokenReplacement(Speech speech, string
tokenKey, string tokenValue)

{
    {
        if (tokenKey == "sprite")

            Animator.Play(tokenValue);
    }

        return string.Empty;
}

And while this does function and calls the animation I name in the speech token, it only does so once--so if I need to change the sprite more than once during a single Dialog action list item, I can't do that.

Is there something I need to include to recognize the speech token more than once per Action List item?

Alternatively, if there's a way for me to use Mecanim while using AC's expression system for the bust sprites, I'm open to that too--I tried switching my NPC to Sprites Unity Complex, and while the on-screen bust sprite's parameters changed, the expressions functionality remained the same.

Comments

  • And while this does function and calls the animation I name in the speech token, it only does so once--so if I need to change the sprite more than once during a single Dialog action list item, I can't do that.

    Sorry, I'm not 100% clear. Are you referring to multiple tokens within the same speech Action, or are other tokens in other Actions within the same ActionList being ignored?

    If you can share screenshots of the ActionList, your Speech Manager's "Subtitles" panel, that'll help clarify the situation.

    To be clear that the tokens specifically aren't being triggered, place a Debug.Log statement inside the OnRequestSpeechTokenReplacement function to check when exactly it's being called, and when.

    What are your AC and Unity versions, also?

    Alternatively, if there's a way for me to use Mecanim while using AC's expression system for the bust sprites, I'm open to that too--I tried switching my NPC to Sprites Unity Complex, and while the on-screen bust sprite's parameters changed, the expressions functionality remained the same.

    I'm not fully clear on the requirements. If the character is 2D, using Sprites Unity Complex will let you map an Integer animator parameter to the current expression ID. How you use that will be up to your Animator Controller.

  • Sure! Sorry for the lack of clarity, I'll try to show what I mean visually.

    With the action list item I provided above, I am trying to use the custom speech event token to trigger an animation to play every time I call the token, similar to how we can call expression changes with the built-in [expression] token.

    However, when I playtest this in Unity, the function only calls one of the animations at a time. Please see below in the following gif (please ignore the visual mess in some places, still WIP haha):

    As you can see above, only the second token, [sprite:OzzieDefaultBlink] animation is called, not [sprite:OzzieDefaultTalk]. I do not have this bust sprite hooked up to the subtitles menu specifically, as when it is, the animation does not call at all--my guess when the bust enables at the same time as the speech, it seems there is not enough time for the token to communicate to the bust sprite image to update/change.

    I am using Unity 2022.3.3f1 and my AC version is v 1.80.4.

    In regards to Sprites Unity Complex, I am now seeing what you mean in regards to the Integer Animator Parameter and I think I understand how it's intended to be used, but I am not sure exactly what information I need to put in this box to hook up the NPC with the animator I want it to reference. I have been attempting to google through Unity animator tutorials but I think I am missing something. If you can lead me in the right direction here I will definitely explore this option too!

  • Where is your script placed, exactly? Are the portraits part of the scene, or a separate Menu? Please try the Debug.Log test I mention above to determine which of the tokens are being processed.

    The token should fire, but it may be that the script isn't active at the time of the first. With the Debug.Log present, and assuming the first isn't displaying, is there a difference if you pad out the start of the line with text, such that the speech doesn't begin with the token?

    I am not sure exactly what information I need to put in this box to hook up the NPC with the animator I want it to reference.

    The Integer parameter would only be applied to the NPC's own Animator - so you'd need to have a script that transfers the parameter value from one to the other.

    The OnStartSpeech event can be used to extract the character speaking, and their GetAnimator function can then be used to get their Animator component.

  • edited September 2024

    Hi Chris,

    Apologies for the double comment, but I spent some time figuring out how to make the animation controller work with AC and feel pretty confident I can use this for what I was trying to jerryrig myself, so please feel free to disregard my question regarding the Speech Event Tokens.

    However, I am still stuck on one thing with the Sprites Unity Complex and Expressions--they don't link up to the bust portrait for some reason?

    As you can see in the gif above, the "BustAnimation" parameter (on the right of the screen) is changing the way I expect it to when I call the [expression] tokens, but the animations are not appearing. I assumed I would be putting these animations on the same/main controller as the smaller on-screen character sprite, but I'm wondering if that's the issue? When I play the animations back in the controller linked to the smaller on-screen sprite, it says "missing"--because the bust sprite is animated separately from the miniature one that is the main hub for the NPC. Is there a specific way I have to hook up the animations for them to appear in the portrait graphic slot on the menu? Do I need to attach a script to the portrait bust image in the menu its self?

    If I plug in the expressions the way you would with Sprites Unity, those animations play, even if Sprites Unity Complex is selected.

    I am attaching below a screenshot of my character parameters and subtitles menu for further clarity on what's going on here.

    Subtitles Menu-related screenshots:

    Character Related screenshots:


    For additional clarity, I did try hooking up the bust animations to the "Any State" target with transitions and it yielded the same result as the gif I showcase above.

    I apologize if I am missing something obvious--I've been googling for a few hours and haven't stumbled upon exactly what I'm missing here.

    Thanks!

  • Is the Animator controller above the one that's changing in the gif? You'll need to add Transitions to it to have the value of the Integer parameter affect which animation gets played.

  • I have tried adding the transitions, but unfortunately I am still in the same boat, I'm assuming because I am not able to communicate from the NPC to the Bust Portrait menu image.

    Let me break down how I understand I need to make this work step by step, and let me know if I've got something wrong:

    1. Create and link up the expression ID integer parameter in the NPC.
    2. Create a script attached to the Bust Portrait menu image that
      a. grabs the expression ID integer from the NPC (I'm assuming on Update so that it will grab the integer each time a new expression token is called?)
      b. Conveys that parameter integer to a separate animator on the Bust Portrait menu image so that it can play the animation it's own animator

    I think where I am getting hung up right now is how to format the script attached to the Bust Sprite image in the menu. Is the Bust Sprite menu image supposed to contain every individual character's portrait? Or is every individual character supposed to have their own separate Bust Portrait menu image that I enable and disable as needed?

    I think if it's something you have time to create in the future, it would be very helpful to have a tutorial built for setting up animated bust sprites using Sprites Unity Complex--I can tell from googling that a lot of people struggle here, and I think it is a feature a lot of people would like to play with!

    Thank you again for your help as always!

  • Yes, you'd need a script that copies over the Integer parameter from one Animator to another. If you have it attached to the Image, you can use the Canvas to extract the Menu it displays for, and then the Speech line it's showing:

    var canvas = GetComponentInParent<Canvas> ();
    var menu = KickStarter.playerMenus.GetMenuWithCanvas (canvas);
    var speaker = menu.speech.GetSpeakingCharacter ();
    var _animator = speaker.GetAnimator ();
    GetComponent<Animator> ().SetInteger ("BustAnimation", _animator.GetInteger ("BustAnimation"));
    

    I'll have to have a think about how a more general solution for more complex animations would be done. How were you animating the "blink" animation from the GIF above?

  • Thanks for clarifying! I was able to hook up the information from the NPC to the bust and now have the animations working. My end goal is to have the ability to display multiple busts on screen at the same time in some scenarios, so I am going to have to figure out a more streamlined way to grab the NPC I want and assign it to the portrait graphic slot rather than going through dialog.IsAnySpeechPlaying and dialog.GetSpeakingCharacter, but that is an issue I will tackle when it is not 1AM, haha!

    In case it helps anyone out who may browse this thread in the future, this is the solution I came up with for now--definitely not streamlined, but a starting point! I have this attached to the Bust Portrait menu image in my Subtitles menu, which has it's own animator.

    {
    
    public Animator BustAnimator;
    
    private void Update()
    
    {
        bool SpeechActive = KickStarter.dialog.IsAnySpeechPlaying();
    
        if (SpeechActive == true)
        { Char character = KickStarter.dialog.GetSpeakingCharacter();
    
    //Which character is speaking
    if (character.name == "CharacterNameHere")
    
    { int WhichExpression = character.GetExpressionID();
    
    if (WhichExpression == 0){ BustAnimator.Play("Expression0"); }
    else if (WhichExpression == 1){ BustAnimator.Play("Expression1"); }
    else if (WhichExpression == 2){ BustAnimator.Play("Expression2"); }
    
    }
    
    }    
    
    }
    
    private void OnDisable() { BustAnimator.Play("Empty"); }
    
    
    }
    

    For the animation in the first gif, I basically jerryrigged a custom Speech Event Token (called [sprite]) that would call an animator hooked up to the Bust Portrait menu image to play the animation I typed as the keytoken. For example, if I typed [sprite:OzzieDefaultBlink], the animator would play the animation titled "OzzieDefaultBlink." Going through [expression] and Sprites Unity Complex is similar, but way better looking and easier to mess with now that I know how to set it up, so definitely a better solution overall!

    Thanks again Chris--I appreciate you being available when I'm trying to punch far above my programming knowledge fighting weight haha!

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.