Samples
A collection of example projects are provided to help you get started with common development scenarios. Read on for instructions to access the samples and brief descriptions of each.
Accessing Samples
The samples are hosted on a private GitHub repository: github.com/naninovel/samples. 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.
Open the repository directory with the Unity editor. Notice that Naninovel is referenced as a Git package in the package manager, so ensure a Git client is installed on your machine. Without it, Unity won't be able to pull the packages; refer to the UPM guide for more info on Git packages.
To use the referenced Naninovel package, you must be authenticated as the GitHub user assigned in the account dashboard. Refer to the Unity guide for more info on authentication. Alternatively, you can remove the Git package reference and install Naninovel from the Asset Store instead.
Addressable
This sample shows how to manually register Naninovel resources with 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 resource manager menus:
— they are still accessible in Naninovel scripts in the same way:
@back Snow
That works, because the assets are assigned a Naninovel resource address and label:
NOTE
Allow Addressable In Editor
has to be enabled in the resource provider configuration in order for the manually registered resources to work in Unity editor.
Perspective Scene
This sample shows a generic background filled with multiple animated environment sprites, camera rendering in perspective mode and bokeh (depth of field) effect. The background is stored at Content/Backgrounds/Perspective
directory.
Compiler Localization
To activate the compiler localization in the sample project, assign Profiles/Naninovel/CompilerRU
asset to the Compiler Localization
field in the scripts configuration. Then restart the Unity editor and VS Code extension. Now you can open the project with VS Code and run Compiler Localization
sample scenario.
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 Scripts/E2E
folder. Notice the .asmdef
file placed in the folder: it's required to compile the test sources under Unity-specific test environment. Also note the testables
entry in the Packages/manifest.json
file, which exposes the tests assembly to the Unity's test runner.
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.
Input Rebind
Documentation: https://naninovel.com/guide/input-processing.html#input-system
An example of input rebinding UI which allows player to change default controls can be found at 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.
Integration
An example project with Naninovel used as both drop-in dialogue for a 3D adventure game and a switchable standalone novel mode.
All the project-specific (example) scripts are stored at Scripts/Runtime/Integration
folder.
Naninovel is initialized manually (auto initialization is disabled in the engine configuration menu) via SetupGame.cs
script attached to SetupGame
game object located on Integration
scene.
DialogueTrigger.cs
script used as component on triggers perform switch to dialogue mode when player is hitting the trigger colliders.
SwitchToNovelMode.cs
custom command is used to switch to novel mode from both C# and naninovel scripts.
SwitchToAdventureMode.cs
custom command is used to switch to adventure from novel mode.
Inventory
While an inventory system is out of scope for visual novels, we had a lot of requests and questions on how to integrate one with Naninovel. The inventory sample serves as an example for creating and integrating an inventory extension, which you can set up on top of Naninovel installation without modifying the engine source code.
NOTE
The inventory is not a standalone product and/or part of Naninovel. Use it to learn how to extend and customize the engine, but don't expect it to be production-ready solution for inventory systems. If you're looking for one, check the Asset Store or create a custom one from scratch.
Example project shows how to make custom inventory UI with grid layout, pagination and drag-drop window, add custom engine service and related configuration menu, add input bindings, use state outsourcing, author custom scenario commands and expression functions.
To create a pre-made inventory UI from template, use Create -> Naninovel -> Inventory -> Inventory UI
asset context menu. Then add the prefab to the Naninovel UI resources via Naninovel -> Resources -> UI
editor menu. Once added, the UI can be shown/hidden like all the other UIs with @showUI
and @hideUI
commands.
The Inventory UI component has Capacity
property, where you can change number of slots in the inventory. Slot grid is configured (slot number and layout, slots per page, etc) via Content/InventoryGrid
game object. Window drag-drop behavior can be configured (disabled) via Drag Drop
component attached to Content
game object.
Inventory item prefabs can be created with Create -> Naninovel -> Inventory -> Inventory Item
asset context menu. The item prefabs will then need to be assigned as inventory resources via Naninovel -> Resources -> Inventory
editor menu.
In case you have a lot of items and it's inconvenient to assign them via editor menu, it's possible to just drop them at Resources/Naninovel/Inventory
folder and they'll automatically be exposed to the engine. You can additionally organize them with sub-folders, if you wish; in this case use forward slashes (/
) when referencing them in naninovel scripts. Eg, item stored as Resources/Naninovel/Inventory/Armor/FullPlate.prefab
can be referenced in scripts as Armor/FullPlate
.
It's also possible to use addressable asset system to manually expose the resources. To expose an asset, assign address equal to the path you'd use to expose it via the method described above, except omit the "Resources/" part. Eg, to expose a "FullPlate.prefab" item, assign the prefab asset following address: Naninovel/Inventory/FullPlate
. Be aware, that addressable provider is not used in editor by default; you can allow it by enabling Enable Addressable In Editor
property in resource provider configuration menu.
Each item has a Stack Count Limit
property to limit how much items of this type can be stacked in a single inventory slot and a On Item Used
Unity event, which is invoked when the item is used (either via @useItem
command or when user clicks on the item in the inventory). Below is an example on how you can set up the event with Play Script
component to remove the item once it used, spawn a glitch special effect and print a text message.
You can add items to the inventory with @addItem
command and remove with @removeItem
(or @removeItemAt
, @removeAllItems
). Item IDs are equal to the item prefab names. Inventory slot IDs are equal to the grid slot indexes (eg, first slot is 0, second is 1, etc).
itemExist()
and itemCount()
custom expression functions to check wither an items exist in inventory and number of existing items are also available for convenience.
Below is a script from the example project:
# Start
Select an action.[< skip!]
@choice "Pick up sword" if:!itemExist("Sword")
@addItem Sword
@choice "Pick up armor" if:!itemExist("Armor")
@addItem Armor
@choice "Adventure awaits, venture forth!"
@stop
# 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 at Content/Characters/Hiyori
and Content/Characters/Senko
directories.
Localization
The generated localization documents are stored at Profiles/Naninovel/Resources/Naninovel/Localization
directory.
The generated sheets are stored at Sheets
directory under the samples project root.
Map
The sample shows how you can implement an interactive map without any C# scripting.
The map is implemented as a custom UI, which is stored at Content/UI/Map
. The locations are regular Unity buttons placed in the UI.
The button's click and hover events are handled with Naninovel's Play Script component.
The availability of the locations is controlled with Variable Trigger components attached to the buttons.
RTL
The RTL printer is stored at Content/Printers/RTL
.
Actor Shader
The example shows how to create and use texture shader for adding custom transition effects and sprite shader with lighting and self-illumination support; the latter is used to simulate time of day for a background actor.
The custom shaders are stored at Scripts/Shaders
directory.
Background texture has 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.
The component API is exposed to naninovel scripts via a Scripts/Runtime/Shader/SetHour.cs
custom command, which allows setting the hour with @hour
command, eg:
; Set current hour to 18:00 (6:00 PM) over 3 seconds.
@hour 18 duration:3
Spine
The sample demonstrates using Spine character with Naninovel. Find it aContent/Characters/Spine
directory.
UI
The sample contains following examples of new custom and modified built-in UIs:
- Title Screen
- Music Gallery
- Credits
- Timestamps in Chat Printer
- Custom Choice Handler
- Emoji in Revealed Messages
- Font Variants in Revealed Messages
- Calendar
— all the sample UIs are stored at Content/UI
.
Layered Actor
Find the layered character at Content/Charecters/Miho
directory and layered background set up in camera rendering mode at Content/Backgrounds/Particles
directory.
Video Actor
Video backgrounds are stored Content/Backgrounds/Video
directory, while a video actor can be found at Content/Characters/Ball
directory.
Visual Scripting
Visual scripting (previously known as Bolt) is a built-in package bundled by default with Unity 2021 and newer version. 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.
First, make sure you're using a compatible Unity version (2021.2 or newer) and Visual Scripting
package is installed in the package manager.
Add Elringus.Naninovel.Runtime
library to the Node Library
list found in "Visual Scripting" project settings menu. This is required to expose engine types and APIs to the visual scripting graphs.
The Visual Scripting doesn't automatically expose all the available types in the libraries, so we additionally need to add the required Naninovel types to the Type Options
list found 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, like the other engine service interfaces, configurations, etc.
Don't forget to regenerate units after adding the libraries and types to apply the changes.
When Naninovel library and types are added in the visual scripting settings, the engine APIs will become available in the fuzzy finder under graph view and can be used in the same way as the other Unity or third-party APIs. Below is an example on initializing the engine and playing a script. Make sure to disable Initialize On Application Load
and remove Title UI
, before trying this example.
In case you wish to send an event from a scenario script to a visual scripting graph or state machine, below is example of a custom command, which will attempt to find a game object with the provided name and send an event with the specified name and arguments:
using Naninovel;
using Unity.VisualScripting;
using UnityEngine;
[CommandAlias("bolt")]
public class BroadcastBoltEvent : Command
{
[ParameterAlias("object"), RequiredParameter]
public StringParameter GameObjectName;
[ParameterAlias("name"), RequiredParameter]
public StringParameter EventName;
[ParameterAlias("args")]
public StringListParameter Arguments;
public override UniTask Execute (AsyncToken token = default)
{
var gameObject = GameObject.Find(GameObjectName);
if (!gameObject)
{
Debug.LogError($"Failed to broadcast '{EventName}' bolt event: '{GameObjectName}' game object is not found.");
return UniTask.CompletedTask;
}
CustomEvent.Trigger(gameObject, EventName, Arguments);
return UniTask.CompletedTask;
}
}
Just copy-paste the contents to a new C# script stored anywhere inside the project Assets directory and the command will automatically become available and can be used as follows:
; 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 a ExampleEvent
game object, will print the message and start playing the specified script.
UniTask
UniTask is an open-sourced (MIT license) library providing a more efficient Task-based asynchronous programming implementation for Unity. You can find more details regarding the nature of optimizations and usage examples in the article by the author of the library.
Naninovel uses a stripped and modified version of UniTask v1, which is embedded inside the engine runtime assembly; most of the asynchronous methods return UniTask
objects, which you can await in the same way as default Task
objects from the "System.Threading" namespace.
In case you want to use full standalone UniTask library, install UniTask v2 from the official repository: github.com/Cysharp/UniTask and specify "Naninovel.UniTask" for the Naninovel APIs when required, eg:
using Naninovel;
using UnityEngine;
public class UniTaskCommand : Command
{
// This method uses embedded UniTask v1.
public override async Naninovel.UniTask Execute (AsyncToken token = default)
{
var message = await WaitAndReturnMessage();
Debug.Log(message);
}
// This method uses standalone UniTask v2.
private async Cysharp.Threading.Tasks.UniTask<string> WaitAndReturnMessage ()
{
await Cysharp.Threading.Tasks.UniTask.DelayFrame(100);
return "Hello from UniTask v2!";
}
}