This is a prerelease version of XVNML.
dotnet add package XVNML --version
NuGet\Install-Package XVNML -Version
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="XVNML" Version="" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add XVNML --version
#r "nuget: XVNML,"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install XVNML as a Cake Addin
#addin nuget:?package=XVNML&version=

// Install XVNML as a Cake Tool
#tool nuget:?package=XVNML&version=


GitHub Nuget (with prereleases) GitHub tag (with filter) Nuget


XVNML (formally known as X-tensible Visual Novel Markup Language), is an open-source mark-up language that can be easily paired with any game engine that requires a nice and structure way of storing Story-Based information and dialogue. It puts together the normal mark up languages you may be used to, but adds a couple extra features (like Skriptr) to make it versitale in you game development work flow.




At it's current stage, these are the following states that this project is in:

  • You can easily import the .dll of XVNML, and add it into any .NET-based game engine or environment (such as Unity).
  • For Unity in particular, there will be a free package that demonstrates and utilizes XVNML called XVNML2U.
  • There still needs to be helpers to make integrating to game engines a lot easier.
  • There will be a Native Visual Novel Game Engine that'll be fully dedicated to XVNML and Skriptr called HanaC.


We'll need your help to make this language unlock its slumbering potential! Supporting us makes sure that we have funds to not only incorporate other technologies with XVNML (such as with the Unity Engine), but it'll also make life a lot easier as we're doing it. Click here to send a donation! A little will mark a large difference!

How to Get Started

You can get started with using XVNML in a variety of ways. Since XVNML was made using C#, you can apply it to any .NET Application you want, whether that'd be on a C# Console, WPF, or ASP.NET application. You can even integrated into Unity, and make it part of your workflow. All it takes is adding the XVNML NuGet package to your project, and you're ready to go! For starters, you can reference off a C# Console Application sample here! You may also want to check out an article I wrote on Medium that walks you through how to install XVNML and integrated in both a C# Console Application and a Unity Project here!

How to Use XVNML

All of your XVNML content are represented by an object called XVNMLObj. You instaniate this class, and pass it in a directory to a file you want it to parse. It'll then go through and parse the information for you, as well as extra any Skriptr used for dialogue. After the parsing, you can grab an element by using the GetElement method on the root tag of the XVNML file.


Pre-Built Tags

By default, you have a total of 32 pre-built tags that can be parsed by the XVNML utility.

  • Args
  • Audio
  • AudioDefinition
  • Author
  • Cast
  • CastDefinition
  • Copyright
  • Date
  • Dependency
  • DependencyGroup
  • Description
  • Dialogue
  • DialogueGroup
  • Image
  • ImageDefinitions
  • Keycode
  • KeycodeDefinitions
  • MacroCache
  • Macro
  • Metadata
  • Portrait
  • PortraitDefinitions
  • Proxy
  • Scene
  • SceneDefinition
  • Source
  • Tag
  • Tags
  • Title
  • Url
  • Voice
  • VoiceDefinition

Out of all of these valid tags, Proxy and Source are Root Tags. This means whenever you type your XVNMLObj instance and access the root, it'll either be Proxy or Source, depending on how the file was structured. A Proxy file is always your main file, and is always read first. However, a Source is a file that can be used to introduce modularity into your projects. For example, the screenshot below shows that we're creating a Cast element called Hana, and the source of that data is in "Hana\Hana.cast.xvnml"

Screenshot 2023-06-25 151133

Screenshot 2023-06-25 151258

By utilizing Source files, you can reduce the number of lines in your proxy file. It's one of the most important best practices of using XVNML in your development process.

User Defined Tags

You also have the ability to create custom tags or User-Defined Tags, thus extending the usage of XVNML (hence the X). Creating a custom class is as easy as associating your C# class with a particular tag.


Once you've created a class that derives from the UserDefined class, you can associate that class with a tag inside your .xvnml file. You can even specifiy its scoop:

  • PragmaOnce ⇒ Should only be mentioned 1 time in a file.
  • PragmaLocalOnce ⇒ Should only be mentioned 1 time inside a scope of another tag.
  • Multiple ⇒ Can be used anywhere, and can be use multiple times thoughout the whole .xvnml document

XVNML file as Sources and Resource Referencing

XVNML files can also be used as sources for other tags. Tag the list of cast members in the CastDefinition tag:


Using a configuration file to find out the relative path of your project, you can take the information from one XVNML and embed it into a tag. For example, this is what the information looks like inside "Raven.cast.xvnml":


It'll take the information from the "cast" tag inside the Raven.cast.xvnml file, and then embed it into the cast tag from the requesting file. It's a very awesome feature exclusive to XVNML. However, the only downside to this is that the "name" parameter for the "cast" tags in both files must match. They will fail to match otherwise.


Skriptr is the syntaxical language used in tandem with XVNML to output text data. Each Skriptr line must first be given a role. It can either take in a Declaratice Role (denoted by the "@" symbol), or an Interrogative Role (denoted by the "?" symbol). When given a Declarative Role, it'll allow the user to, for example, output text to the screen. However, if given an Interrogative Role, the dialgoue comes a Prompt that requires user input.

You are also able to run macros (a single-unit command that performs one or more functions). Information of the command used, as well as the arguments passed will be stored inside your XVNMLObj instance. A macro is denoted by surrounding curly braces. The macro name is first defined, and then the argument(s) being passed for it (if the macro requires them).

Another feature with Skriptr is the ability to name lines using square brackets. Combining macros such as "jump_to" and "lead_to", you're able to use named lines to control the flow of dialogue.

$> XVNML Example
@ Unfortunately, that's not the correct answer...{jump_to::"P1-Skriptr-CorrectAnswer"}<

@ Skriptr is the syntaxical language used in tandem with XVNML to...<
@ type out dialogue.<
@ Each Skriptr line must first be given a role to play.<
@ It can either take in a Declarative Role {paren}denoted by the {quot|at|quot} symbol{paren_end}...<
@ Or a Interrogative Role {paren}denoted by the {quot|qm|quot} symbol {paren_end}...<
@ When given a Declarative Role, it'll type out dialogue to the screen as normal...{delay::500|clr}
Just like what you are seeing now.<
@ However, if given a Interrogative Role...<
@ The dialogue acts as a Prompt in which the user must answer to.<
? For example, how many states does the United States have?>>
          @ That is correct!<<
          @ {jump_to::"P1-Skriptr-Incorrect"|pass}<<
          @ {jump_to::"P1-Skriptr-Incorrect"|pass}<<
     ("I honestly don't know...")>
          @ That's okay if you don't know.<<

@ There are 50 states that makes up the United States of America.<
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated 57 4/17/2024
1.0.3-pre-release 52 4/12/2024 71 9/13/2023 71 9/13/2023 60 9/13/2023 72 7/17/2023 68 8/3/2023 66 7/11/2023
1.0.1-pre-release 69 7/11/2023 66 6/27/2023 58 6/26/2023 59 6/22/2023
1.0.0-pre-release 58 6/21/2023

- We've released a patch where data for XVNML macros doesn't remain persistent when generating a cache file.
- We've also allowed for the user to set a destination path for all cached data (for the XVNML Object and the Cached Macros that it depends on).