Skip to content

Samples

While the Naninovel package already includes a couple of essential samples to help you get started with Visual Novel and Dialogue Mode scenarios, an additional collection of specialized samples is provided to demonstrate common development use cases. Read on for instructions on how to access these samples and brief descriptions of each.

Accessing Samples

The advanced samples are hosted under the engine's monorepo ↗. To access the repository, register your Naninovel license ↗ and follow the dashboard instructions to assign a GitHub user. Once you have access, either clone ↗ or download ↗ the repository.

Unzip the downloaded repository and open the unity/samples directory in the Unity Editor. Naninovel is referenced as a local package in the Package Manager. The local package source points to unity/client, which contains the source code of the Unity extension. Other third-party packages used in the samples are embedded in the project for convenience.

cover

Once in the Unity Editor, open the Assets/Scenes/Main.unity scene and enter Play mode. You'll see the title screen of our demo project ↗. You can either start the demo or click the "SAMPLES" button to navigate the available samples, which are outlined below.

cover

Addressable

This sample shows how to manually register Naninovel resources with the addressable provider (without using resource editor menus) and serve the assets from a remote host.

Notice that while most of the resources in the sample project are not assigned in the resource manager menus:

cover

—they are still accessible in scenario scripts in the same way:

nani
@back Snow

That works because the assets are assigned a Naninovel resource address and label:

cover

Perspective Scene

This sample shows a generic background filled with multiple animated environment sprites, camera rendering in perspective mode, and a bokeh (depth-of-field) effect. The background is stored in the Content/Backgrounds/Perspective directory.

cover

Compiler Localization

To activate compiler localization in the sample project, assign the Profiles/Naninovel/CompilerRU asset to the Compiler Localization field in the Scripts configuration. Then restart the Unity Editor and the VS Code extension. Now you can open the project with VS Code and run the Compiler Localization sample scenario.

cover

E2E

The E2E Tests sample shows how to set up an automated end-to-end tests suite and use most of the available APIs.

The test scripts are stored under the Scripts/E2E folder. Note the .asmdef file placed in the folder: it's required to compile the test sources under the Unity test environment. Also note the testables entry in the Packages/manifest.json file, which exposes the tests assembly to Unity's test runner.

cover

Generic Actor

Find Content/Backgrounds/Beach, Content/Backgrounds/Perspective generic backgrounds and Content/Characters/Kohaku/K3D generic character showing how to set up and use the generic actor implementation with 3D models and animations authored with Unity's Animator.

cover

Input Rebind

Documentation: https://naninovel.com/guide/input-processing.html#input-system ↗

An example input-rebinding UI that allows the player to change default controls can be found in the Content/UI/InputRebind folder. It's based on the "Rebind UI" sample bundled with the Input System package; find more info in the Unity documentation ↗.

cover

Integration

An example project demonstrating Naninovel used as both a drop-in dialogue system for a 3D adventure game and a switchable standalone novel mode.

cover

All project-specific example scripts are stored in the Scripts/Runtime/Integration folder.

Naninovel is initialized manually (auto initialization is disabled in the engine configuration menu) via the SetupGame.cs script attached to the SetupGame GameObject located in the Integration scene.

The DialogueTrigger.cs script, used as a component on triggers, switches to dialogue mode when the player hits the trigger colliders.

The SwitchToNovelMode.cs custom command is used to switch to novel mode from both C# and scenario scripts.

The SwitchToAdventureMode.cs custom command is used to switch back to adventure mode from novel mode.

Inventory

While an inventory system is out of scope for visual novels, we received many requests and questions on how to integrate one with Naninovel. The inventory sample is an example of creating and integrating an inventory extension that you can set up on top of a Naninovel installation without modifying the engine source code.

NOTE

The inventory is not a standalone product or part of Naninovel. Use it to learn how to extend and customize the engine, but don't expect it to be a production-ready solution for inventory systems. If you're looking for one, check the Asset Store ↗ or create a custom one from scratch.

This example project shows how to make a custom inventory UI with grid layout, pagination, and a drag-and-drop window; add a custom engine service and related configuration menu; add input bindings; use state outsourcing; and author custom scenario commands and expression functions.

cover

To create a pre-made inventory UI from a template, use the Create -> Naninovel -> Inventory -> Inventory UI asset context menu. Then add the prefab to the Naninovel UI resources via Naninovel -> Resources -> UI in the editor. Once added, the UI can be shown/hidden like all other UIs with the @showUI and @hideUI commands.

The Inventory UI component has a Capacity property where you can change the number of slots in the inventory. The slot grid is configured (slot number and layout, slots per page, etc.) via the Content/InventoryGrid GameObject. Window drag-and-drop behavior can be configured (or disabled) via the Drag Drop component attached to the Content GameObject.

Inventory item prefabs can be created with the Create -> Naninovel -> Inventory -> Inventory Item asset context menu. The item prefabs will then need to be assigned as inventory resources via Naninovel -> Resources -> Inventory in the editor.

cover

If you have many items and it's inconvenient to assign them via the editor menus, you can drop them in the Resources/Naninovel/Inventory folder and they'll automatically be exposed to the engine. You can additionally organize them with subfolders; in this case use forward slashes (/) when referencing them in scenario scripts. For example, an item stored as Resources/Naninovel/Inventory/Armor/FullPlate.prefab can be referenced in scripts as Armor/FullPlate.

It's also possible to use the Addressable Asset System to manually expose the resources. To expose an asset, assign an address equal to the path you'd use via the method described above, but omit the Resources/ part. For example, to expose a FullPlate.prefab item, assign the prefab the address Naninovel/Inventory/FullPlate. Be aware that the Addressable provider is not used in the Editor by default; you can enable it by turning on the Enable Addressable In Editor property in the resource provider configuration menu.

Each item has a Stack Count Limit property to limit how many items of this type can be stacked in a single inventory slot, and an On Item Used Unity event, which is invoked when the item is used (either via the @useItem command or when the user clicks on the item in the inventory). Below is an example of how to set up the event with a Play Script component to remove the item once it is used, spawn a glitch special effect, and print a text message.

cover

You can add items to the inventory using the @addItem command and remove them with @removeItem (or @removeItemAt, @removeAllItems). Item IDs are equal to the item prefab names. Inventory slot IDs are equal to the grid slot indexes (e.g., the first slot is 0, the second is 1, etc.).

itemExist() and itemCount() custom expression functions to check whether an item exists in inventory and to get the number of existing items are also available for convenience.

Below is a script from the example project:

nani
# Start

Select an action.[>]

@choice "Pick up sword" lock:itemExist("Sword")
    @addItem Sword
@choice "Pick up armor" lock:itemExist("Armor")
    @addItem Armor
@choice "Adventure awaits, venture forth!"

# Adventure

@if itemExist("Sword")
	@set monstersSlayed={ itemExist("Armor") ? random(3,5) : 2 }
	@addItem Food amount:{monstersSlayed}
	You've encountered and slayed {monstersSlayed} monsters with your sword.
	@goto #Start
@else
	But you don't have a weapon! You've been beaten by the monsters.
	@goto #Start

Live2D

The sample demonstrates using Live2D characters with Naninovel. Find them in the Content/Characters/Hiyori and Content/Characters/Senko directories.

cover

Localization

  • The generated localization documents are stored in the Profiles/Naninovel/Resources/Naninovel/Localization directory.
  • The generated sheets are stored in the Sheets directory under the samples project root.
  • The localization-specific font is stored in Profiles/Naninovel/Resources/Naninovel/Fonts.

Folders selected for localization tool:

FolderPath
Script Folder (input)Assets/Scripts/Scenario
Text Folder (input)Assets/Profiles/Naninovel/Resources/Naninovel/Text
Locale Folder (output)Assets/Profiles/Naninovel/Resources/Naninovel/Localization

Folders selected for spreadsheet tool:

FolderPath
Input Scripts FolderAssets/Scripts/Scenario
Input Text FolderAssets/Profiles/Naninovel/Resources/Naninovel/Text
Input Localization FolderAssets/Profiles/Naninovel/Resources/Naninovel/Localization
Output FolderSheets
cover

Map

The sample shows how you can implement an interactive map without any C# scripting.

cover

The map is implemented as a custom UI stored at Content/UI/Map. The locations are regular Unity buttons placed in the UI.

cover

The buttons' click and hover events are handled by Naninovel's Play Script ↗ component.

cover

The availability of the locations is controlled with Variable Events ↗ components attached to the buttons.

RTL

The RTL printer is stored at Content/Printers/RTL.

cover

Actor Shader

The example shows how to create and use a texture shader for adding custom transition effects and a sprite shader with lighting and self-illumination support; the latter is used to simulate time of day for a background actor.

cover

The custom shaders are stored in the Scripts/Shaders directory.

The background texture has a self-illumination mask stored in the alpha layer, which is used by the custom shader to evaluate which areas should emit light while ignoring the global light.

Time of day is controlled with Scripts/Runtime/Shader/TimeOfDay.cs, which allows configuring light color and emission intensity at any given point of a 24-hour day.

cover

The component API is exposed to scenario scripts via the Scripts/Runtime/Shader/SetHour.cs custom command, which allows setting the hour with the @hour command, e.g.:

nani
; Set current hour to 18:00 (6:00 PM) over 3 seconds.
@hour 18 duration:3

Spine

The sample demonstrates using Spine characters with Naninovel. Find them in the Content/Characters/Spine directory.

cover

UI

The sample contains the following examples of new custom and modified built-in UIs:

  • Title Screen
cover
  • Music Gallery
cover
  • Credits
cover
  • Timestamps in Chat Printer
cover
  • Custom Choice Handler
cover
  • Emoji in Revealed Messages
cover
  • Font Variants in Revealed Messages
cover
  • Calendar
cover

All the sample UIs are stored in Content/UI.

Layered Actor

Find the layered character at the Content/Characters/Miho directory and the layered background set up in camera rendering mode at Content/Backgrounds/Particles.

Diced Actor

Find the diced character and atlas at Content/Characters/Kohaku/Diced.

Video Actor

Video backgrounds are stored in the Content/Backgrounds/Video directory, while a video actor can be found in the Content/Characters/Ball directory.

Scene Background

Find the scene background in the Content/Backgrounds/Scene directory.

Transition Effects

Find a demo with all the available transition effects applied in sequence in the Scripts/Scenario/Transitions scenario script.

Auto Voicing

The voice clips for EN and JA locales are stored under Content/Audio/Voice.

Enter the "AUTO VOICING" sample and try switching the voice language in game settings.

Music Intro

Shows how to use the intro parameter of the @bgm command so that the intro part is played once before looping the base part of the track.

Background Matching

A demo of the background matching feature, showing how backgrounds with different aspect ratios can be matched to the display viewport.

Visual Scripting

Visual Scripting ↗ (previously known as Bolt) is a built-in package bundled by default with Unity 2021.2 and newer. It enables you to create logic for games or applications with unit-based graphs that both programmers and non-programmers can use without writing code.

cover

First, make sure you're using a compatible Unity version (2021.2 or newer) and that the Visual Scripting package is installed in the Package Manager.

cover

Add the Elringus.Naninovel.Runtime library to the Node Library list found in the Visual Scripting project settings. This is required to expose engine types and APIs to the visual scripting graphs.

cover

Visual Scripting doesn't automatically expose all available types from libraries, so add the required Naninovel types to the Type Options list in the same settings menu. In the example below we added Engine, Script Player Interface, and Script Player Extensions, but you'll probably need more types, such as the other engine service interfaces, configurations, etc.

cover

Don't forget to regenerate units after adding the libraries and types to apply the changes.

cover

When the Naninovel library and types are added in the Visual Scripting settings, the engine APIs will become available in the fuzzy finder under the graph view and can be used like other Unity or third-party APIs. Below is an example of initializing the engine and playing a script. Make sure to disable Initialize On Application Load and remove Title UI before trying this example.

cover

If you wish to send an event from a scenario script to a visual scripting graph or state machine, below is an example of a custom command that will attempt to find a GameObject with the provided name and send an event with the specified name and arguments:

csharp
[Serializable, Alias("bolt")]
public class BroadcastBoltEvent : Command
{
    [Alias("object"), RequiredParameter]
    public StringParameter GameObjectName;
    [Alias("name"), RequiredParameter]
    public StringParameter EventName;
    [Alias("args")]
    public StringListParameter Arguments;

    public override Awaitable Execute (ExecutionContext ctx)
    {
        var gameObject = GameObject.Find(GameObjectName);
        if (!gameObject)
        {
            Debug.LogError($"Failed to broadcast '{EventName}' bolt event: '{GameObjectName}' game object is not found.");
            return Async.Completed;
        }

        CustomEvent.Trigger(gameObject, EventName, Arguments);

        return Async.Completed;
    }
}

Just copy-paste the contents to a new C# script stored anywhere inside the project's Assets directory and the command will automatically become available and can be used as follows:

nani
; Send "MyEvent" to "ExampleEvent" game object with the provided args
@bolt object:ExampleEvent name:MyEvent args:ExampleMessage,Script002

Below is an example graph that, when attached to an ExampleEvent GameObject, will print the message and start playing the specified script.

cover