Skip to content
Paul Joannon edited this page Jul 28, 2023 · 4 revisions

Disclaimer

This documentation is about the GodotInk versions aimed at Godot 4.

The documentation for Godot 3 is currently unavailable, but you can find a couple of examples directly in the repository here.


☄️ Installation

The following instructions assume that you have a working Godot and .NET installation. If not, please refer to the official engine documentation.

Installing GodotInk in your project is a four step process.

  1. Download and extract the code at the root of your project. You should see a new addons/GodotInk/ folder in your project's directory.

  2. Add the following line in your .csproj file (before the closing </Project> tag).

    <Import Project="addons\GodotInk\GodotInk.props" />

    If you don't have a .csproj file, click the Create C# Solution button in the editor's Project/Tools menu.

  3. Build your project once.

  4. Enable GodotInk in your project settings.

🌠 Quick start guide

Once everything is set up, you are able to see your .ink files in Godot. A new Ink Preview tab also appears in the bottom panel.

This guide covers enough ground to get you started. We're going to import a story stored in a .ink file, preview it quickly directly in the editor, and write a simple Godot scene running that story.

We are assuming you have a basic knowledge of both ink and Godot.

All set? Here we go.

The ink importer

Select one of your .ink files and go to the Import dock. You'll see it reads "Import As: Ink Story". A couple of import settings are also available. Check the Is Main File checkbox and click Reimport. Any error or warning coming from the compiler will be reported in the Output bottom panel.

The ink previewer

Go to the Ink Preview bottom panel, click the Load button and navigate to the story you imported earlier. Now click the Start button on the right. Your story will start being displayed in the panel: the text and tags on the left, and the choices on the right.

The runtime

Create a new scene with VBoxContainer as its root type, attach a new script to the root, and add an exported field of type InkStory to that script.

The InkStory class is defined in the GodotInk namespace.

using Godot;
using GodotInk;

public partial class QuickStartGuide : VBoxContainer
{
    [Export]
    private InkStory story;
}

Go back to Godot, and click the Build button. A Story property is now visible in the inspector when you select the root node of the scene. Click the selection box, scroll all the way down to Load, and select the .ink story you imported earlier.

In the code, the story field is your handle on the content of this .ink file. In order to get a line of content, you need to call the story.Continue() method.

Add the following to your class. When running the game, you'll see the first sentence of your story be printed in the Output panel.

public override void _Ready()
{
    GD.Print(story.Continue());
}

But let's rollback. The goal isn't to print the content in that panel, it's to show it in the game. Let's write the following logic:

  • Retrieve all the content until the next set of choices.
  • Display the content on the screen.
  • Retrieve the choices.
  • Display those choices as buttons on the screen.

Remove the GD.Print(...); line we added earlier, and in its place write the following. It creates a new Label node, and injects all the available content into it.

Label content = new() { Text = story.ContinueMaximally() };
AddChild(content);

If you launch the game now, you'll see all the content prior to the first set of choices displayed on screen. Now to add the choices, the story.CurrentChoices property accesses a List<InkChoice> containing all the information you need. Do pretty much the same thing as before, only in a loop, and with Button nodes instead of Label.

foreach (InkChoice choice in story.CurrentChoices)
{
    Button button = new() { Text = choice.Text };
    AddChild(button);
}

Feel free to run the game and check the new buttons are here. At this point, you probably realize that you'll need to run all of this logic again once a choice is selected, so the next chunk of content is displayed. An easy way to do this is to grab all the code you wrote until now and put it in its own method. Call it ContinueStory() for instance.

private void ContinueStory()
{
    Label content = new() { Text = story.ContinueMaximally() };
    AddChild(content);

    foreach (InkChoice choice in story.CurrentChoices)
    {
        Button button = new() { Text = choice.Text };
        AddChild(button);
    }
}

Don't forget to add a call to ContinueStory() in the _Ready() method.

The last (well, next to last 👀) thing to do is to make something happen when the player clicks the buttons: choose that option and move the story forward. Add this inside the foreach block, between the button creation and its addition to the SceneTree:

button.Pressed += delegate
{
    story.ChooseChoiceIndex(choice.Index);
    ContinueStory();
};

You can read it like "When the button is pressed, choose the corresponding index, and move the story along".

Again, feel free to run the project at any time to check how things are going. If you pay attention, we never clean the old text and choices we add along the way, and it will quickly become annoying. You can do it at the very beginning of the ContinueStory() method.

foreach (Node child in GetChildren())
    child.QueueFree();

And done! You have created a very bare-bones runner for your ink stories. Run the game to see it in action. It's probably ugly, maybe some lines are too long and don't fit the screen, but it works. And it's only the foundation on which you're going to build upon. It'll work with any story, simply switch the reference like we did at the beginning and restart the game.

There is a lot more to GodotInk. The API available through InkStory gives access to all the features (almost, this version is still a work in progress) of the ink runtime: variables, functions, observers, flows, etc.

But all of this is out of scope for this guide. You can find the full script at the bottom of the page if need be. The API is (or will be) described and explained in depth in other documentation pages.

For suggestions, bug reports and feedback, do not hesitate to use the issue tracker. You can also find me on social media (links are on my GitHub profile).

ko-fi


QuickStartGuide.cs

using Godot;
using GodotInk;

public partial class QuickStartGuide : VBoxContainer
{
    [Export]
    private InkStory story;

    public override void _Ready()
    {
        ContinueStory();
    }

    private void ContinueStory()
    {
        foreach (Node child in GetChildren())
            child.QueueFree();

        Label content = new() { Text = story.ContinueMaximally() };
        AddChild(content);

        foreach (InkChoice choice in story.CurrentChoices)
        {
            Button button = new() { Text = choice.Text };
            button.Pressed += delegate
            {
                story.ChooseChoiceIndex(choice.Index);
                ContinueStory();
            };
            AddChild(button);
        }
    }
}