CharacterImage in Dialogue

So what I try to do is actually having a character image for every single DialogueNode. So that I can add some kind of impressions depending on what answer I choosed. So the problem that I am facing is the following. I can hook up the characterImage in the inspector for every single Dialogue Node shown in the picture:

Well the actual problem is, that when I go from the first AI node to the Players choice node, the image won’t actually update cause it is still the first AI node but we are simply hiding the AI text and enable the players choice. So how can I actually manage to go from the first AI Node to the actual second (Players Node) after hitting the next button?

Something along the line of checking to see if the player is choosing.

If you want the player’s expression on each of the choice nodes, this is rather easy, in DialogueUI.BuildChoiceList()

        private void BuildChoiceList()
        {
            foreach (Transform item in choiceRoot)
            {
                Destroy(item.gameObject);
            }
            foreach (DialogueNode choice in playerConversant.GetChoices())
            {
                GameObject choiceInstance = Instantiate(choicePrefab, choiceRoot);
                var textComp = choiceInstance.GetComponentInChildren<TextMeshProUGUI>();
                textComp.text = choice.GetText();

                //Add Character image
                Image choiceImage = choiceInstance.GetComponent<Image>();
                choiceImage = choice.GetCharacterImage();
                
                Button button = choiceInstance.GetComponentInChildren<Button>();
                button.onClick.AddListener(() => 
                {
                    playerConversant.SelectChoice(choice);
                });
            }
        }

Well what I actually want, is of course having different images on the dialogue nodes. So that also on all of the different player nodes I can actually change the image.

So in the PlayerConversant I am getting the character Image

  public Sprite GetCharacterImage()
    {
        if (currentNode == null)
        {
                return null;
        }
        
        return currentNode.GetImage(); 
    
        
    }

Wich is actually attached in the DialogueNode.cs

  [SerializeField]
        Sprite characterImage;
      
       
        public Sprite GetImage()
       {
        return characterImage;
       }

The main struggle I have and it is a bit hard to explain is the following. The first dialogue node of the AI runs through. When I hit the Next Button, of course the Next() function in the PlayerConversant will be activated BUT It only runs through the if statement

if(numPlayerResponses > 0)
         {
            isChoosing = true;
            TriggerExitAction();
            onConversationUpdated();
            return;
         }

And that’s why It won’t actually update the first AI DialogueNode to the second Player Dialogue Node. That’s the reason why the image won’t update, cause were are still “stucked” in the first AI DialogueNode, even if the player choices are already shown.

After I hit next again and go to the last AI DialogueNode it will show the right image again but that’s cause now the SelectChoice() function will be called, that wasn’t called on the first next button push.

Soory for my bad englisch Brian, but I hope you understand what’s the main problem about me trying to having different images in every single DialogueNode

In DialogueUI.UpdateUI(), we should be disabling the AI response and enabling the Player response when the player is choosing:

        AIResponse.SetActive(!playerConversant.IsChoosing());
        choiceRoot.gameObject.SetActive(playerConversant.IsChoosing());

If we use a different image for the AIResponse and the choiceRoot, then we just need to set the image accordingly in the next if statement:

            if (playerConversant.IsChoosing())
            {
                BuildChoiceList();
            }
            else
            {
                AIText.text = playerConversant.GetText();
                nextButton.gameObject.SetActive(playerConversant.HasNext());
                characterImage.sprite = playerConversant.GetCharacterImage();
            }

It’s here I would set the appropriate image.
The tricky part is that if the source of the player image is the DialogueNode, when you have multiple choices, which image do you choose? Personally, I would leave the earlier code in place, with each choice instance having it’s own image component.
If you just want one that works for both the player and the AI, don’t put the character image sprite in the AIResponse or choiceRoot, and you can set the player’s in the if(playerConversant.IsChoosing()) with this:

characterImage.sprite = playerConversant.GetChoices().First.GetImage();

I am sorry Brian but I don’t think we are speaking about the same issue and solution for it. Cause I tried that one yesterday I already, yes putted the characterImage in the else statement will show the image for the AI when he is speaking BUT the main problem is the following:

As you said right, in the UpdateUI() we are disabling the AI response and enabling the Player response when we for example hit the next Button but the problem is, that the first time we are doing that, we actually stay at the first AINode and won’t update it.

So the chain is like this:

  1. We start talking to an AI and his Dialogue appears.
  2. Then we hit the next Button which will NOT update the Node(so the ID of the Node stays the same). We stay at the same node but simply disabling the AI Response and enabling the PlayersChoices.
  3. We hit an choice answer and finally the Node will be Updated cause it will call the function SelectChoice().

And in Part 2 is the problem, when it shows the Players Choices we are actually still in the current node of the first AI Response, cause with the first next Button we click, the only thing that will be called is this if Statement in the Next() function:

 int numPlayerResponses = FilterOnCondition(currentDialogue.GetPlayerChildren(currentNode)).Count();

         if(numPlayerResponses > 0)
         {
            isChoosing = true;
            TriggerExitAction();
            onConversationUpdated();
            return;
         }

And it confuses me too much, cause why is it going through this if- statement, when we are still at the first AI Node and there we don’t even have a number of Player Responses.

So the only solution I somehow need, is that the Node gets actually updated when we hit the next Button for the first time and calling the Players response for the first time

Here I also made a little cycle of how this actually work at the moment and what’s the problem about it:

I hope that my problem now is a little bit cleaner? And we can find a solution for that :slight_smile:

The problem with this is if you have multiple responses, going to the 2nd node would cut off access to all the other nodes. While the problem looks straightforward in your graph, that’s because there is only one child node off of the root node. You can’t move to the child node until the player has made a choice. It’s a structural issue.
However, the IsChoosing lets the UI know that we should be using the child nodes of the current dialoguenode to form our list of choices instead of displaying the current node. This allows us to see all the available choices.

Thanks Brian for the explanation :slight_smile: So that means it is kind of hard to fixing this issue? If so, I would just let it with text and not adding those images :slight_smile:

I still believe this is doable, entirely through the UI. The key is in the if(playerConversant.IsChoosing()) block in DialogueUI.UpdateUI()

If isChoosing, display the first Choice’s image (or on each choice, put the image that corresponds to the choice and disable the speaker image).
If !isChoosing, set the speaker image to the currentNode’s image.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms