<aside> 💡 This article is written for developers of all experience levels. However, it may be helpful to understand the basics of the ConvoGen editor.
</aside>
ConvoGen is a powerful dialogue editor tool that allows users to create dynamic dialogue trees for their games (and other media, too!). Its easy-to-use API can be easily integrated into projects and consumed with only a few lines of code.
Table of Contents
<aside> 💡 The following editor concepts will be helpful in setting up the sample ConvoGen test project: Nodes, Dialogue Components, Choice Components
</aside>
Before we add the API, we must create a simple ConvoGen project.
The end result is to have a starting node with some dialogue, followed by two choices that lead to child nodes.
Now we need to export the project into .cvg format for the API to consume. In the upper left corner of the window click File → Export. Save the export file in an easily accessible location with the name APITestExport.cvg.
<aside> 💡 To make this code work with Unity, simply create a new script and place this code in the Start(), then replace any Console.WriteLine() calls with Debug.Log(). Finally, create an empty GameObject in your scene and attach the script.
</aside>
Now the fun part: reading the .cvg file. This code will be written in your initialization code for your engine, but to be engine-agnostic, let’s create a new C# project and write this in the Main() method.
In Visual Studio 2022, click Create a new project. In the next window, select Console App. For Project Name, enter APIExample and click Next.
In the Additional information window, select your desired .NET version (depending on your engine; for this example, the latest version is fine) and check do not use top-level statements and click Create.
Now we should have a boilerplate Program.cs with a Main method. Most of our code will be written within Main, except for a reusable method we will use to output the results.
namespace APIExample
{
internal class Program
{
static void Main(string[] args)
{
}
}
}
In order to access the API in code, we need to add the ConvoGen API DLL as a reference.
In Visual Studio, click View → Solution Explorer. Expand the APIExample project and right click Dependencies. Click Add Project Reference.
Click the Browse button. In the file browser, navigate to the ConvoGen application folder and select both ConvoGen.API.dll and Newtonsoft.Json.dll. Click Add and then click OK.
Now we can access the ConvoGen.API classes from within our code.
First, we need to import the .cvg file into memory. In the Main method, add the following lines, changing the filepath to wherever your previously-exported .cvg file is located.
var path = @"C:\\Path\\To\\My\\APIExampleExport.cvg";
var projectLoadResult = ConvoGenAPI.LoadProject(path);
// Notify success/failure of project load (optional)
if (projectLoadResult.Success)
{
Console.WriteLine("ConvoGen project loaded successfully");
}
else
{
Console.WriteLine(projectLoadResult.Message);
}
// Output the logs from project load (optional)
foreach (var log in project.Logs.GetLogs())
{
Console.WriteLine(log.LogText);
}
Now we can begin to read the data we just loaded. Next, we must tell the API which Sequence to load. To do that, we have to know the Id of the sequence, which we can find in the ConvoGen Editor. Select our Sequence’s name in the left sidebar, and look at the Id property in the right sidebar. Select the value and copy it using CTRL+C.
The Id property is the internal identifier of the Sequence. This property is how the API interacts with the data within the .cvg format.
Next, we will instruct the API to enter our Sequence, which sets the current node to the Sequence’s starting node. Then we will begin execution.
// Pull out the project from the result so we don't have to keep
// typing "projectLoadResult".
var project = projectLoadResult.Result;
// Enter a sequence by Id (found in the right sidebar in ConvoGen when
// a sequence is selected).
Console.WriteLine("Entering sequence...");
var enterSequenceResult = project.EnterSequence(Guid.Parse("af55ad69-8370-4d9e-8c1d-e07796e5266e"));
// Execute the current node.
// This will return every dialogue until execution encounters a branch/choice
// that requires user input.
// Note: this means more than one node can be executed.
Console.WriteLine("Executing...");
var nodeExecutionResult = project.ExecuteCurrentNode();
ExecuteCurrentNode() will begin execution until it encounters a stopping point, which is generally a Choice, the end of the Sequence, or an error. The NodeExecutionResult that is returned will represent the execution state since the last time ExecuteCurrentNode() was called.
Now that we have our NodeExecutionResult, we need to display it in the console. Let’s add another method below the Main() method since we will reuse this code.
private static void outputResult(ConvoGen.API.Classes.NodeExecutionResult nodeExecutionResult)
{
//Output every dialogue from the previous execution.
Console.WriteLine("Dialogue:");
foreach (var dialogueComponent in nodeExecutionResult.Dialogues)
{
Console.WriteLine(dialogueComponent.DialogueText);
}
//Output the choices for the user to select.
Console.WriteLine("Choices:");
foreach (var choiceComponent in nodeExecutionResult.Choices)
{
Console.WriteLine("" + choiceComponent.ChoiceText);
}
}
And don’t forget to call outputResult() in our Main method:
//Output the result of the execution
outputResult(nodeExecutionResult);
Running this code, we should get the following:
Loading ConvoGen project...
ConvoGen project loaded successfully
Building indexes...
Entering sequence...
Executing...
Dialogue:
This is the starting node.
Choices:
Node 2
Node 3
As you can see, we get the initialization output, followed by the dialogue, and then the text representing each choice.
Now that we’ve returned the dialogue and choices for one execution cycle, how do we make a choice?
In a real game or application, the UI would take this dialogue and choice text and present it to the user. The user’s selection would then inform the API which choice to execute. However, for these purposes, we will assume the user selected the first choice.
//Here is where the options would be presented to the user in the application.
//Let's assume the user wanted to pick the first option.
var choiceToSelect = nodeExecutionResult.Choices.First();
//Execute the current choice.
//This sets the current node to the choice's linked node.
project.ExecuteChoice(choiceToSelect);
//Continue the execution.
nodeExecutionResult = project.ExecuteCurrentNode();
//Output again.
outputResult(nodeExecutionResult);
//Confirm the sequence has ended.
//In a real application, here the dialogue box would be closed and play would resume.
if (nodeExecutionResult.SequenceEnded) Console.WriteLine("Sequence ended");
After this execution cycle, we see the following:
Dialogue:
This is node 2.
Choices:
Sequence ended
Here we see the dialogue from node 1 (which was choice 1 in the starting node), and no additional choices. Because the execution reached a dead end, the SequenceEnded property became true.
<aside> 💡 In your real game or app, events can be used to be notified when things happen, like the end of a sequence. This approach allows for more dynamic code, eliminating the need for continuously checking the SequenceEnded property as shown above.
</aside>
Congratulations! You have successfully navigated a Sequence from the ConvoGen API.
static void Main(string[] args)
{
//Load ConvoGen export data.
var path = @"C:\\Path\\To\\My\\APIExampleExport.cvg";
if (!System.IO.File.Exists(path)) Console.WriteLine("Path doesn't exist.");
//Tell the API to initialize the project.
var projectLoadResult = ConvoGenAPI.LoadProject(path);
if (projectLoadResult.Success)
{
Console.WriteLine("ConvoGen project loaded successfully");
}
else
{
Console.WriteLine(projectLoadResult.Message);
}
var project = projectLoadResult.Result;
//Output any errors or messages that occurred during load.
foreach (var log in project.Logs.GetLogs())
{
Console.WriteLine(log.LogText);
}
//Enter a sequence by Id (found in the right sidebar in ConvoGen when a sequence is selected).
Console.WriteLine("Entering sequence...");
var enterSequenceResult = project.EnterSequence(Guid.Parse("af55ad69-8370-4d9e-8c1d-e07796e5266e"));
//Since we entered the sequence, the current node is the starting node of the sequence.
//Execute the current node.
//This will return every dialogue until execution encounters a branch/choice that requires user input.
//Note: this means more than one node can be executed with this call.
Console.WriteLine("Executing node...");
var nodeExecutionResult = project.ExecuteCurrentNode();
//Output the result of the execution
outputResult(nodeExecutionResult);
//Here is where the options would be presented to the user in the application.
//Let's assume the user wanted to pick the first option.
var choiceToSelect = nodeExecutionResult.Choices.First();
//Execute the current choice.
//This sets the current node to the choice's linked node.
project.ExecuteChoice(choiceToSelect);
//Continue the execution.
nodeExecutionResult = project.ExecuteCurrentNode();
//Output again.
outputResult(nodeExecutionResult);
if (nodeExecutionResult.SequenceEnded) Console.WriteLine("Sequence ended");
}
private static void outputResult(ConvoGen.API.Classes.NodeExecutionResult nodeExecutionResult)
{
//Output every dialogue from the previous execution.
Console.WriteLine("Dialogue:");
foreach (var dialogueComponent in nodeExecutionResult.Dialogues)
{
if (dialogueComponent.Person != null)
{
Console.WriteLine(dialogueComponent.Person.PersonName);
}
Console.WriteLine(dialogueComponent.DialogueText);
}
//Output the choices for the user to select.
Console.WriteLine("Choices:");
foreach (var choiceComponent in nodeExecutionResult.Choices)
{
Console.WriteLine("" + choiceComponent.ChoiceText);
}
}