Skip to content

Voicing

To expose voice clips to the engine, store them under Resources/Naninovel/Voice folder (can be changed in audio configuration under Loader foldout). You can additionally organize them with sub-folders, if you wish; in this case use forward slashes (/) when referencing them in naninovel scripts. Eg, voice audio clip stored as Resources/Naninovel/Voice/Intro/Day/25.wav can be referenced in scripts as Intro/Day/25.

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 "Hello.wav" voice clip, assign the clip asset following address: Naninovel/Voice/Hello. 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.

You can use any audio formats supported by Unity ↗ for your voice clips.

Voice playback behavior can be configured using Naninovel -> Configuration -> Audio context menu; for available options see configuration guide.

Use @voice command followed by the clip name (path) to play the voice in naninovel scripts, eg:

nani
@voice Hello

— will play a voice clip asset stored at Resources/Naninovel/Voice/Hello.wav.

NOTE

The @voice commands are intended to occasionally play voice clips at specific moments and are not suited for implementing a complete voiceover; see the "Auto Voicing" section below for more information on how to handle voicing in projects, where most of the text lines have an associated voice clip. Some built-in features (eg, replay voice in backlog, voiceover documents, etc) works only with the auto voice workflow.

Auto Voicing

In fully-voiced games, it could become tedious to specify a @voice command for each voiced line. Auto voicing feature allows automatically playing voice clip associated with either playback spot or unique text identifier (default). To enable auto voicing feature, enable Enable Auto Voicing toggle in the Audio configuration menu.

cover

The association mode can be selected in the audio configuration via Auto Voice Mode option. Playback spot mode is less robust and considered legacy; please check out Text ID mode description below and if for some reason it won't suit you, continue reading about Playback spot mode.

Text ID

Text ID mode associates voice clips with localizable text identifiers. The association can be performed either via voice map utility or by assigning addresses to audio clip assets with Unity's addressable asset system (or otherwise exposing the assets to another resource provider).

When Text ID mode is selected, an "Open Voice Map Utility" button will appear in the audio configuration menu; you can also access the utility via Naninovel -> Tools -> Voice Map editor menu.

cover

First, select script file for which to map the voice clips. If the selected script contains any print commands (or generic text lines), they will be listed in pairs with audio clip fields. Drop (or select) a voice clip via the field to associate voice with the text. It's also possible to auto-map the clips; for this name the clip assets equal to the start of the voiced line text and drag the clips (or folder with the clips) to the voice map utility.

WARNING

When assigning the clips via voice map window, make sure to store the voice clips outside any "Resources" folders to prevent conflicts.

To associate voice clips for non-source locale, pick script localization document with Localization Document field. When valid document is picked, assigned voice clips will be automatically prefixed with the locale under which the document is stored and used whe corresponding voice language is selected.

In cases same author have equal text messages (in the same script), both messages will be associated with the same voice clip. If that is not desired, add unique text identifier to one of the messages, eg:

nani
Hello.
Hello.|#uniqueid|

TIP

Enable Stable Identification under scripts configuration menu to make Naninovel automatically generate unique IDs for all localizable script text, including voiced lines. This way you won't have to manually assign IDs for duplicate lines and editing already mapped lines won't break the associations. See text identification for more info.

To associate the clips without using voice map utility, expose the assets to a resource provider using text ID as the resource name prefixed by the voice loader prefix (Voice by default). To find text ID of a particular text, use voiceover documents; the ID is displayed after voice's playback spot prefixed by #. For example, to associate a line with 2670eb4 ID with addressable resource provider, use the following address Naninovel/Voice/2670eb4.

To find text ID associated with the currently printed text while the game is running use debug window:

auto voicingcover

To show the window, make sure Enable Development Console is turned on in the engine configuration, then press ~ key while in play mode, type debug and press Enter.

Playback Spot

Legacy playback spot mode will automatically play voice clip that has name equal line number of the currently played @print command. This works fine as long as the voiceover is added after scenario scripts are finished, but when working on voicing and authoring/editing scripts at the same time, you may find yourself constantly changing voice clip names to accommodate edits in the associated scripts. For this reason we recommend using Text ID mode, where associations won't break when editing scenario.

Audio clips used with playback spot mode should be grouped under a folder with name equal to the script name, and has the following name: LineNumber.CommandIndex, where LineNumber is the line number of the corresponding print command and CommandIndex is the inline or command index of the print command in cases when dealing with generic text lines.

For example, consider the following naninovel script with name "Script001":

nani
@print text:"Text from a print command."
Text from a simple generic text line.
Text from first sentence.[i] Text from second sentence.

In order for the auto voicing system to play corresponding audio clips when printing those lines, the clips should be placed under Resources/Naninovel/Voice/Script001 folder (or registered with addressable system) and have the following names:

TextVoice Clip Name
Text from a print command.1.0
Text from a simple generic text line.2.0
Text from first sentence.3.0
Text from second sentence.3.2

The voice clip names will be displayed in debug window instead of IDs when the mode is selected.

Author Volume

When using auto voicing, you may want to let players control voice volume for specific characters or, more correctly, authors of the printed text messages. For example, a player may decide to mute voice of the main protagonist or make a specific character voice lower.

To set up per-author voice control, create a custom settings UI, add a new slider (you can duplicate "VoiceVolumeSlider" already present in the prefab) and specify author (character) ID in the Author ID field.

cover

The added slider will now control voice volume of the specified character. When nothing is assigned to the author ID field, the slider will control volume of the audio mixer's voice group, affecting all the voices.

Voice Language

When adding voice over for different localizations, it's possible to allow player to select the voice language independently of the main localization (eg, play the game with English text and UI, but with Japanese voice over).

To add voice language dropdown to the game settings, assign Voice Locales property in the audio configuration menu. Add the language tags of the locales for which you have the corresponding voice resources. Eg, the example below will allow the player to choose from English and Japanese voices:

cover

When the property is assigned, "Voice language" dropdown will appear in the game settings menu:

cover

For more information on how to localize game resources, see the localization guide.

Voiceover Documents

The voiceover documents are intended to be used by the voice recording engineers and actors when producing the voiceover audio.

Use voiceover documents generator utility accessible via Naninovel -> Tools -> Voiceover Documents to generate the documents, containing printed text from the @print commands and generic text lines. Each printed text message will be associated with the auto voice clip name and hash to be used with the auto voicing feature.

cover

Locale property allows to select a specific locale for which to generate the documents (the localized naninovel scripts for the selected locale should exist in your project).

Format property controls type of file and formatting of the voiceover documents to produce:

  • Plaintext — Plaintext file without any formatting.
  • Markdown — Markdown ↗ file with additional formatting for better readability.
  • CSV — Comma-separated values ↗ file to be used with table processors, such as Google Sheets or Microsoft Excel.

Below is an example of a voiceover document generated with Markdown format.

cover

Custom Generator

It's possible to inject custom voiceover document generator in case you wish to format and/or serialize the documents in a special way.

To add custom generator, create a new C# class with a parameterless constructor and implement IVoiceoverDocumentGenerator interface. The utility will automatically pick such class and use it instead of the built-in generators.

GenerateVoiceoverDocument method will be invoked by the utility for each script found in the project for the selected locale. list argument is the list of commands contained in the script. locale represents the locale (language) selected in the utility. outDir is the output path selected in the utility.

Below is an example of a custom voiceover generator, which appends a header with script name and locale followed by voice path and hash > author > text line for each print text command found in the script.

csharp
public class VoiceoverGenerator : IVoiceoverDocumentGenerator
{
    public void GenerateVoiceoverDocument (ScriptPlaylist list, string locale, string outDir)
    {
        var builder = new StringBuilder();
        builder.AppendLine($"Voiceover for '{list.ScriptName}' ({locale} locale)");
        foreach (var cmd in list.OfType<PrintText>())
        {
            var voicePath = AudioConfiguration.GetAutoVoiceClipPath(cmd.PlaybackSpot);
            var voiceHash = AudioConfiguration.GetAutoVoiceClipPath(cmd);
            builder.AppendLine($"{voicePath} #{voiceHash} > {cmd.AuthorId} > {cmd.Text}");
        }
        File.WriteAllText($"{outDir}/{list.ScriptName}.txt", builder.ToString());
    }
}