In my game I have multiple actors that can speak during dialogue. Some of them are characters that can die during gameplay.
I'd like to have this concept of a "generic" dialogue entry where I might have Actor 1 defined as the actor for the dialogue entry, but if they are dead, I could use actor 2 or 3 (or whatever) instead.
I couldn't figure out how to implement this change of the actor during runtime on per-entry basis.
Any suggestions?
Dynamically changing the actor of a Dialogue entry during runtime
Re: Dynamically changing the actor of a Dialogue entry during runtime
Hi,
Create a generic actor in your dialogue database, and use this as the conversation's conversant.
Create/use GameObjects for your actors. Add Dialogue Actor components to them, and set the Actor dropdown to each one's actor.
At runtime, pass an actor's GameObject to the Dialogue System Trigger's Conversation Conversant field or the DialogueManager.StartConversation(title, actor, conversant) C# method to start a conversation. Wherever the generic actor was referenced in the original conversation in your database, this actor will be used instead. More info: Character GameObject Assignments
Create a generic actor in your dialogue database, and use this as the conversation's conversant.
Create/use GameObjects for your actors. Add Dialogue Actor components to them, and set the Actor dropdown to each one's actor.
At runtime, pass an actor's GameObject to the Dialogue System Trigger's Conversation Conversant field or the DialogueManager.StartConversation(title, actor, conversant) C# method to start a conversation. Wherever the generic actor was referenced in the original conversation in your database, this actor will be used instead. More info: Character GameObject Assignments
Re: Dynamically changing the actor of a Dialogue entry during runtime
Hey, while this works for some of my usecases, is it possible to change the actor of a dialogue entry that has some other actor than the conversant of the conversation?
So for example if I have A1, the "generic" actor, as the conversant of the conversation, but I have some entries in the conversation where A2 is speaking, and maybe A3 later in the conversation, but A2 and A3 might be dead on this specific game "run". So in this scenario I'd like for some other actor to fallback in their place. So in a way I'd like to treat the dialogue entries that A2 and A3 now are speaking as "generic" in a way that it could be spoken by some other characters too.
Is this possible?
EDIT:
What I ended up doing is that I created my own singleton class where I have defined "fallback actors" per actor, and then modified the source code, specifically ConversationModes.cs GetState method, where it sets the CharacterInfo with the dialogue entry's ActorID. Something like this:
This solution could've been achieved with Conditions and entry groups, but it's a lot of work to add all of these fallbacks, so this system just works immediately for all of my dialogue.
I did also add a new field to Dialogue Entry template that I can use to mark entries as non-generic, that will make them ignore this fallback system, and work "normally".
So for example if I have A1, the "generic" actor, as the conversant of the conversation, but I have some entries in the conversation where A2 is speaking, and maybe A3 later in the conversation, but A2 and A3 might be dead on this specific game "run". So in this scenario I'd like for some other actor to fallback in their place. So in a way I'd like to treat the dialogue entries that A2 and A3 now are speaking as "generic" in a way that it could be spoken by some other characters too.
Is this possible?
EDIT:
What I ended up doing is that I created my own singleton class where I have defined "fallback actors" per actor, and then modified the source code, specifically ConversationModes.cs GetState method, where it sets the CharacterInfo with the dialogue entry's ActorID. Something like this:
Code: Select all
public ConversationState GetState(DialogueEntry entry, ...)
{
...
var actorId = entry.ActorID;
if(fallbackSystem.TryGetFallbackActorId(actorId, out int fallbackActorId) {
actorId = fallbackActorId;
}
CharacterInfo actorInfo = GetCharacterInfo(actorId);
...
}
I did also add a new field to Dialogue Entry template that I can use to mark entries as non-generic, that will make them ignore this fallback system, and work "normally".
Re: Dynamically changing the actor of a Dialogue entry during runtime
Hi,
Instead of directly modifying the source code, you may want to use an OnPrepareConversationLine(DialogueEntry) method or OnConversationLine(Subtitle) method (see Script Methods) to change the actor. This way you won't lose your customizations when you update the Dialogue System.
Instead of directly modifying the source code, you may want to use an OnPrepareConversationLine(DialogueEntry) method or OnConversationLine(Subtitle) method (see Script Methods) to change the actor. This way you won't lose your customizations when you update the Dialogue System.
Re: Dynamically changing the actor of a Dialogue entry during runtime
Alright thanks for the pointer!
OnPrepareConversationLine(DialogueEntry) wasn't an option as editing the ActorID seems to be persistent, and I only want it to be for that specific time. But I found a solution from the other option!
I changed it to this:
OnPrepareConversationLine(DialogueEntry) wasn't an option as editing the ActorID seems to be persistent, and I only want it to be for that specific time. But I found a solution from the other option!
I changed it to this:
Code: Select all
public void OnConversationLine(Subtitle subtitle)
{
if (subtitle.dialogueEntry == null) return;
if (TryGetFallbackActorId(subtitle.dialogueEntry, out var fallbackActorId))
{
subtitle.speakerInfo = DialogueManager.Instance.ConversationModel.GetCharacterInfo(fallbackActorId);
}
}
Re: Dynamically changing the actor of a Dialogue entry during runtime
Sounds good. OnConversationLine is the preferable option. If you ever do need to use OnPrepareConversationLine, tick the Dialogue Manager's Other Settings > Instantiate Database so it has a runtime copy that you can change without modifying the actual asset.
Re: Dynamically changing the actor of a Dialogue entry during runtime
Ah good to know!
I think even that wouldn't work in my scenario as I want this change to be only for this specific subtitle instance, so having a copy DB would still have a persistent change to the dialogue entry for the play session I think?
Anyways, thanks!
I think even that wouldn't work in my scenario as I want this change to be only for this specific subtitle instance, so having a copy DB would still have a persistent change to the dialogue entry for the play session I think?
Anyways, thanks!
Re: Dynamically changing the actor of a Dialogue entry during runtime
Yes, that's correct about it being persistent. So OnConversationLine is definitely the way to go in this case.