Integrating with your game - enriquemorenotent/unity-conversa-support GitHub Wiki
Conversa is a plugin which focuses on one thing and one thing only. Designing your conversations. But that is all. It will not force you to use any kind of prefab of construct to integrate it within your game, and your UI. This is an advantage and a disadvantage at the same time. There will be no out-of-the-box solutions just so you can drag and drop a prefab onto your scene, and have it running (at least not for now). But this also means that you will not have to adapt the architecture of your project because Conversa forces you too.
Luckily, you have at your disposal a very simple and straightforward API that will let you integrate your conversations with your UI in a very simple and elegant matter. Let's see a case of how it can be done.
Define the UI API
Let's say that your game has a very classic UI like many other games, to present your conversations to the user.

We all have seen hundreds of times this kind of pattern in many games. It basically presents itself with a small text window, where you can read the message displayed, as well as the actor who is talking at the moment.
Typically, you will want to wrap your UI with a controller script, something like UIController.cs, for example. In this tutorial I am going to assume that this class exists, and it exposes these methods in its API.
// A method to show a message, and define the action to take, after having read it
public void ShowMessage(string actor, string message, Action action);
// A method to show a message and choices the user can take
public void ShowChoice(string actor, string message, Option[] options);
// A method to hide the UI
public void Hide();
Having these elements defined, let's build a controller to stitch up our conversations with our UI.
Building a Conversa controller
First, we will create a new GameObject component called ConversaController.
public class ConversaController : MonoBehaviour
{
[SerializeField] private Conversation conversation;
[SerializeField] private UIController uiController;
private ConversationRunner runner;
private void Start()
{
runner = new ConversationRunner(conversation);
runner.OnConversationEvent.AddListener(HandleConversationEvent);
}
public void Begin()
{
runner.Begin();
}
private void HandleConversationEvent(IConversationEvent e) { ... }
}
This component will have three private fields, two of them serialized to be accessible through the inspector.
conversationwill be the object holding the conversation that we want to use.uiControllerwill be a reference to the UI Controller that we may have built for our game.runnerwill be a ConversationRunner.
A conversation runner is a helper class that will help you take a conversation, and navigate the flow of this, from one node to the next one. In the Start method, we will initialize runner, and add an event handler for the OnConversationEvent event.
Finally, we will define a Begin method, so that the runner can begin traversing the conversation. This public method can be invoked, for instance, from a button inside your scene.
Handling events
As the runner moves its cursor along the flow of the conversation, depending on which nodes it lands, it will fire different kind of events. There are many kinds of events possible, and you can extend them defining even more, but the natives ones are MessageEvent, ChoiceEvent, ActorMessageEvent, ActorChoiceEvent, UserEvente and EndEvent.
private void HandleConversationEvent(IConversationEvent e)
{
switch (e)
{
case MessageEvent messageEvent:
HandleMessage(messageEvent);
break;
case ChoiceEvent choiceEvent:
HandleChoice(choiceEvent);
break;
case ActorMessageEvent actorMessageEvent:
HandleActorMessageEvent(actorMessageEvent);
break;
case ActorChoiceEvent actorChoiceEvent:
HandleActorChoiceEvent(actorChoiceEvent);
break;
case UserEvent userEvent:
HandleUserEvent(userEvent);
break;
case EndEvent _:
HandleEnd();
break;
}
}
The name of the events are quite self-explanatory. MessageEvent gets fired where the cursor in the conversation lands in a message node, and ChoiceEvent get fired when it lands on a choice node. Notice that there are 2 similar events called ActorMessageEvent and ActorChoiceEvent. These methods have exactly the same purpose, but they are used when the actor of the message is defined with an instance of an "Actor" object, instead of a plain string.
USerEvent is fired when the cursor lands in a user-defined event node, which allows you to react within your game any way that you prefer. Finally, the EndEvent gets fired when you reach the end of the conversation.
Handling events
Now let's see how we can handle each one of those events.
private void HandleMessage(MessageEvent e)
{
uiController.ShowMessage(e.Actor, e.Message, () => e.Advance());
}
private void HandleChoice(ChoiceEvent e)
{
uiController.ShowChoice(e.Actor, e.Message, e.Options);
}
private void HandleActorMessageEvent(ActorMessageEvent evt)
{
uiController.ShowMessage(evt.Actor.DisplayName, evt.Message, evt.Advance);
}
private void HandleActorChoiceEvent(ActorChoiceEvent evt)
{
uiController.ShowChoice(evt.Actor.DisplayName, evt.Message, null, evt.Options);
}
private static void HandleUserEvent(UserEvent userEvent)
{
if (userEvent.Name == "Food bought")
Debug.Log("We can use this event to update the inventory, for instance");
}
private void HandleEnd() => uiController.Hide();
Here you can see how depending on the event received, we interact with our UIController differently, passing them the adequate parameters, depending on the method that we are going to be using.
Special mention has the HandleUserEvent method. In the case, we simply show a debug message, but you will most likely want to do something inside your game with it. To create a relationship of event names, with the actions that need to be taken you could, for instance, create a dictionary of Pairs <string, System.Action>, where depending on the fired user event, the game system reacts differently.
Wrapping up
As you can see, the API is not really complicated at all. Integrating it with your system is probably going to be as complicated, as your own game's system is. Think carefully when you build your system what is the best way to hook things up, and you should not have any problem integrating Conversa within your game.