Forum rules - please read before posting.

Creating Composite Portrait Images

edited March 2020 in Technical Q&A

Hi Chris

I'm currently working on a system that will allow me to generate random 2d characters (either NPC, or Player). Conceptually it's similar to the Character Creator 2d, except that it uses my own graphics and randomizing/display system, and it uses classic sprite animation rather than the new-fangled Unity stuff

So far the development has gone suspiciously smoothly, to the point that I actually have a working prototype in my Template AC Project

The one remaining problem area, is that I can't quite envisage the best way to create corresponding Dialogue Portraits

So, for example, imagine that an NPC Actor Portrait consists of a Face, a Pair of Glasses overlaid on top of that, and a Hairpiece overlaid on top of that, as HERE for example, (except that in the eventual system all of the different elements will also be tinted)

I wonder if you could give me any suggestions as to what you think would be the best way to tackle something like that? I'd like to still be able to use the Dialogue ActionList (or an equivalent thereof), in order to be able to use Expression tokens (which would obviously be applied to the base Face Image)

One possibility would be to create a composite portrait dynamically, when the character is first randomized, and then use the Character: Switch Portrait ActionList to set it, but I'm not really sure how to implement the compositing part of the process, and a quick browse of the Unity forums suggests that it isn't likely to be straightforward, so I guess it might be better to just overlay each of the elements on top of each other somehow, at the point of displaying the portrait?

Comments

  • Challenging though it may be, dynamically generating portrait textures at runtime is certainly doable and a viable option. I'd be inclined to take that approach, personally.

    The overlay method would still allow use of speech Actions, though not the "Dialogue Portrait" fields / element type. I'd expect you'd start with a Unity UI Canvas whereby each part is arranged on top of each other. So in your example, the "head", "glasses" and "hair" would be displayed in three separate Image components with the same RectTransform values.

    You'd then need to set these Image components to the correct sprites when a character speaks. The sprites to use (or textures, if you use RawImage components) would be recorded in a custom component attached to the character, and then assigned to the UI Canvas when they speak via the OnStartSpeech event.

    So let's say this is attached to your Subtitles UI Canvas:

    using UnityEngine;
    using UnityEngine.UI;
    
    public class PortraitSetter : MonoBehaviour
    {
    
        public Image faceImage, glassesImage, hairImage;
    
        public void AssignSprites (Sprite faceSprite, Sprite glassesSprite, Sprite hairSprite)
        {
            faceImage.sprite = faceSprite;
            glassesImage.sprite = glassesImage;
            hairImage.sprite = hairImage;
        }
    
    }
    

    Where "Face Image" etc are assigned in the Inspector to the Image components.

    Then this would be attached to your Character:

    using UnityEngine;
    using UnityEngine.UI;
    using AC;
    
    public class PortraitOverlayExample : MonoBehaviour
    {
    
        private Sprite faceSprite, glassesSprite, hairSprite; // These are set upon character creation
    
        private void OnEnable () { EventManager.OnStartSpeech += StartSpeech; }
    
        private void StartSpeech (AC.Char character, string lineText, int lineID)
        {
            if (character == GetComponent <Char>())
            {
                // This character is speaking
                PortraitSetter portraitSetter = PlayerMenus.GetMenuWithName ("Subtitles").RuntimeCanvas.GetComponent <PortraitSetter>();
                portraitSetter.AssignSprites (faceSprite, glassesSprite, hairSprite);
            }
        }
    
    }
    

    That should do it for single images, but expressions would be a bit more complex. You'd have to use your own token instead of the provided "[expression:ID]" token, and then rely on speech event tokens to update the Image components in the same way. See the Manual's "Speech event tokens" for more on this topic.

  • Thanks for the feedback Chris, it's much appreciated

    Following your suggestion I'll continue researching the possibility of dynamically generating the portraits at runtime (it would be a useful technique to know even if I don't happen to use it this time); but I rather think that the easier option (given my limited skillset) will be to go down the overlay route

    I can visualise how that would work, and I kinda suspect that it might also turn out to be the more flexible option when it comes to creating expressions

    Once again, thanks for taking the time and trouble to give such clear advice

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.