Assigning sprites to an actor's portraits

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
Nokinori
Posts: 9
Joined: Tue Jun 27, 2023 5:11 pm

Assigning sprites to an actor's portraits

Post by Nokinori »

I've written a script for a custom playmaker action that allows me to assign a new sprite as an actor's portrait. My goal is to assign a new portrait sprite, then have the old one fade to the new one over a short period of time which I can specify. I thought the easiest way might be to assign the new sprite as the actor's second portrait, fade from the first to the second, assign the same image to the first portrait image, then switch back to the first so that the second is available for the next transition. Unfortunately, I'm having trouble figuring out how to assign sprites to specific portrait images.

I'm using a composite sprite system I created, so the sprites are dynamically generated by a script, then assigned to the sprite component of a spriteRenderer, and then that sprite component is saved as a playmaker Sprite variable. Then I'm using this playmaker action to assign that Sprite variable to the dialogue actor's portrait image.

Is there a better way to accomplish this?

Here is my playmaker action code:

Code: Select all

[ActionCategory("Dialogue")]
[HutongGames.PlayMaker.TooltipAttribute("Sets an actor's portrait")]
public class SetDialogueActorPortrait : FsmStateAction
{
    [RequiredField]
    [HutongGames.PlayMaker.TooltipAttribute("The name of the actor in the dialogue database")]
    public FsmString actorName;

    [RequiredField]
    [ObjectType(typeof(Sprite))]
    [HutongGames.PlayMaker.TooltipAttribute("The new portrait sprite to set")]
    public FsmObject newPortrait;

    public override void Reset()
    {
        actorName = null;
        newPortrait = null;
    }

    public override void OnEnter()
    {
        var sprite = newPortrait.Value as Sprite;
        if (sprite != null)
        {
            Actor actor = DialogueManager.MasterDatabase.GetActor(actorName.Value);
            if (actor != null)
            {
                actor.spritePortrait = sprite;
            }
        }
        
        Finish();
    }
}
And here was an attempt to set specific portraits:

Code: Select all

    public override void OnEnter()
    {
        var sprite = newPortrait.Value as Sprite;
        if (sprite != null)
        {
            Actor actor = DialogueManager.MasterDatabase.GetActor(actorName.Value);
            if (actor != null && actor.spritePortraits != null)
            {
                // Update the second portrait
                actor.spritePortraits[2] = sprite;
            }
        }

        Finish();
    }
actor.spritePortraits[x] with any number x gives me the error ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
User avatar
Tony Li
Posts: 22110
Joined: Thu Jul 18, 2013 1:27 pm

Re: Assigning sprites to an actor's portraits

Post by Tony Li »

Hi,

Try actor.spritePortrait for the main portrait and actor.spritePortraits[0] for the alternate portrait. The actor.spritePortraits list holds the alternate portraits (not the primary one).

The Dialogue System Extras page has an Animated Change Post Example (direct download) that cross-fades between portraits. It might be overkill for what you're looking for, but it might give you some ideas about how to approach the cross-fade. Each Portrait Image GameObject has a child Crossfade Image GameObject. To cross-fade, the Portrait Image's Image > Color > Alpha goes to zero and the Crossfade Image's Image > Color > Alpha goes to 1.
Post Reply