Integration Options
While Naninovel is focused around traditional visual novel games and works best as a template for one, it's possible to integrate the engine with existing projects. If you're making a 3D adventure game, RPG or game of any other genre — you can still use Naninovel as a drop-in dialogue system.
There are multiple ways you can integrate Naninovel with a custom project and specific implementation will depend on the type of the project and what exactly you want to achieve with Naninovel. In the following documentation we'll list various configuration options and API that could be useful for "pairing" Naninovel with a standalone game. Before you continue, take a look at the engine architecture to better understand how it behaves on a conceptual level.
EXAMPLE
Check out an example project, where Naninovel is used as both drop-in dialogue for a 3D adventure game and a switchable standalone novel mode.
Manual Initialization
When Initialize On Application Load
option in the engine configuration menu is enabled, the engine services will automatically initialize on application start.
Unless you want to begin your game in novel mode, you would rather manually initialize the engine when it's actually needed by either invoking a static RuntimeInitializer.Initialize()
method from C# or adding a Runtime Initializer
component to a game object on scene; the latter will make the engine initialize when the scene is loaded in Unity.
Below is an example of manual initialization from a MonoBehaviour ↗ script:
using Naninovel;
using UnityEngine;
public class MyScript : MonoBehaviour
{
private async void Start ()
{
await RuntimeInitializer.Initialize();
}
}
Disabling Scene Independent
option will make all the Naninovel-related objects part of the Unity scene where the engine was initialized; the engine will be destroyed when the scene is unloaded.
To reset the engine services (and dispose most of the occupied resources), use ResetState()
method of IStateManager
service; this is useful, when you're going to temporary switch to some other gameplay mode, but be able to return to novel mode without re-initializing the engine.
To destroy all the engine services and completely remove Naninovel from memory, use Engine.Destroy()
static method.
Accessing Engine API
The engine initialization procedure is asynchronous, so even when automatic initialization is enabled, engine APIs may not be available right after Unity loads a scene (eg, in Awake
, Start
and OnEnable
MonoBehaviour ↗ methods).
To check whether the engine is currently available, use Engine.Initialized
property; Engine.OnInitializationFinished
event allows executing actions after the initialization procedure is finished, eg:
public class MyScript : MonoBehaviour
{
private void Awake ()
{
// Engine may not be initialized here, so check first.
if (Engine.Initialized) DoMyCustomWork();
else Engine.OnInitializationFinished += DoMyCustomWork;
}
private void DoMyCustomWork ()
{
// Engine is initialized here, it's safe to use the APIs.
var scriptPlayer = Engine.GetService<IScriptPlayer>();
...
}
}
Playing Naninovel Scripts
To preload and play a naninovel script with a given path, use LoadAndPlay(ScriptPath)
method of IScriptPlayer
service. To get an engine service, use Engine.GetService<TService>()
static method, where TService
is the type (interface) of the service to retrieve. For example, the following will get a script player service, then preload and play a script with name "Script001":
var player = Engine.GetService<IScriptPlayer>();
await player.LoadAndPlay("Script001");
When exiting the novel mode and returning to the main game mode, you probably would like to unload all the resources currently used by Naninovel and stop all the engine services. For this, use ResetState()
method of a IStateManager
service:
var stateManager = Engine.GetService<IStateManager>();
await stateManager.ResetState();
Disable Title Menu
A built-in title menu implementation will be automatically shown when the engine is initialized, while you'll most likely have your own title menu. You can either modify, replace or completely remove the built-in title menu using UI customization feature. The menu goes under Title UI
in the UI resources list.
Engine Objects Layer
You can make the engine assign a specific layer ↗ for all the objects (except UI-related) it creates via configuration menu.
This will also make the engine's camera to use culling mask ↗ and render only the objects with the specified layer.
To change layer of the UI objects managed by the engine, use Objects Layer
option in the UI configuration menu.
Render to Texture
You can make the engine's camera render to a custom render texture ↗ instead of the screen (and change other camera-related settings) by assigning a custom camera prefab in camera configuration menu.
Switching Modes
While it heavily depends on the project, following is an abstract example (based on the integration project mentioned previously) on how you can implement switching between "adventure" and "novel" modes via custom commands.
[CommandAlias("novel")]
public class SwitchToNovelMode : Command
{
public StringParameter ScriptPath;
public StringParameter Label;
public override async UniTask Execute (AsyncToken asyncToken)
{
// 1. Disable character control.
var controller = Object.FindObjectOfType<CharacterController3D>();
controller.IsInputBlocked = true;
// 2. Switch cameras.
var advCamera = GameObject.Find("AdvCamera").GetComponent<Camera>();
advCamera.enabled = false;
var naniCamera = Engine.GetService<ICameraManager>().Camera;
naniCamera.enabled = true;
// 3. Load and play specified script (if assigned).
if (Assigned(ScriptPath))
{
var scriptPlayer = Engine.GetService<IScriptPlayer>();
await scriptPlayer.LoadAndPlay(ScriptPath, label);
}
// 4. Enable Naninovel input.
var inputManager = Engine.GetService<IInputManager>();
inputManager.ProcessInput = true;
}
}
[CommandAlias("adventure")]
public class SwitchToAdventureMode : Command
{
public override async UniTask Execute (AsyncToken asyncToken)
{
// 1. Disable Naninovel input.
var inputManager = Engine.GetService<IInputManager>();
inputManager.ProcessInput = false;
// 2. Stop script player.
var scriptPlayer = Engine.GetService<IScriptPlayer>();
scriptPlayer.Stop();
// 3. Reset state.
var stateManager = Engine.GetService<IStateManager>();
await stateManager.ResetState();
// 4. Switch cameras.
var advCamera = GameObject.Find("AdvCamera").GetComponent<Camera>();
advCamera.enabled = true;
var naniCamera = Engine.GetService<ICameraManager>().Camera;
naniCamera.enabled = false;
// 5. Enable character control.
var controller = Object.FindObjectOfType<CharacterController3D>();
controller.IsInputBlocked = false;
}
}
The commands can then be used in naninovel scripts:
; Switch to adventure mode.
@adventure
— or directly in C# (eg, in OnTrigger
Unity events):
private void OnTriggerEnter (Collider other)
{
var switchCommand = new SwitchToNovelMode { ScriptPath = "Script001" };
switchCommand.Execute().Forget();
}
Other Options
There are multiple other features (state outsourcing, services overriding, custom serialization, resource and configuration providers, etc), which could be situationally helpful when integrating the engine with another systems; check out rest of the guide for more information. Consider investigating the available configuration options as well; some feature may not be described in the guide, but still be handy for integration purposes.
If you feel some engine API or system is lacking in extendability and requiring source code modification in order to integrate, please contact the support — we'll consider improving it.
EXAMPLE
An example project with Naninovel used as both drop-in dialogue for a 3D adventure game and a switchable standalone novel mode is available on GitHub ↗.