
Please view the README for information regarding installation and usage!
Descant is a Unity dialogue system plugin. The Unity Asset Store is chock full of many such types of plugins, ranging from feature-rich, to ultra-minimalist, to downright bad. Descant aims to hit the sweet spot between quality UI, powerful features, and easy-to-lean functionality, while also addressing many of the game-specific consequences of the standard dialogue manager setup. Besides acting as a standard tool for creating, saving, and actualizing non-linear game dialogue, it also pushes the envelope by adding optional dialogue-enhancing node components that introduce features to break away from the overused and underwhelming trends seen in many interactive fiction games. These enhancements act similar to Unity's standard GameObject Component system, and can be applied at-will to nodes. This modular approach is so-far not explored in the world of Unity dialogue systems. The project will be free (and collaborative open-source) forever. Feel free to send me a message or submit a pull request if you want to make any changes.
Component documentation
A number of Descant Components come bundled with the system by default. They cover a wide range of applications, and can be edited at-will. Please see the next section, Component creation, for a guide on how to write your own Components in C#.
ChangedChoice
Changes the text of one of a ChoiceNode's choices if some condition is met.
Max Quantity: None
Node Type(s): Choice
Variables:
Actor: A reference to the actor who's variable is being checked
ChoiceNumber: The index of the choice being changed (base 1)
VariableType: The type of the variable being checked (e.g. Statistic, Topic, etc.)
VariableName: The name of the variable being checked
ComparisonType: The type of the comparison being performed against the variable
Comparison: The value to compare the variable against
ChangeTo: The text to change the choice to if the comparison succeeds
ChangedResponse
Changes the text of a ResponseNode's response if some condition is met.
Max Quantity: None
Node Type(s): Response
Variables:
Actor: A reference to the actor who's variable is being checked
VariableType: The type of the variable being checked (e.g. Statistic, Topic, etc.)
VariableName: The name of the variable being checked
ComparisonType: The type of the comparison being performed against the variable
Comparison: The value to compare the variable against
ChangeTo: The text to change the choice to if the comparison succeeds
Event
Calls a method from a script.
Max Quantity: None
Node Type(s): Any
Variables:
ObjectTag: The tag of the GameObject on which the script is located (optional)
ScriptName: The name of the script on the GameObject
MethodName: The name of the method being called
Parameter: The parameter to pass to the method (optional)
Disclaimers:
If ObjectTag is empty, the first found script in the scene with the given name is called instead.
If the ScriptName or MethodName are empty, no method is called.
While Parameter is technically of type string, Integers and Floats can also be written, and will be parsed accordingly.
Currently, methods with more than one parameter cannot be called.
Interruptable
Allows for the dialogue to be abruptly stopped with a key or button press. Once this happens, a method from a script can be called.
Max Quantity: None
Node Type(s): Response
Variables:
KeyCode: The lowercase name of the key press to check for (e.g. "e", "space", etc.) (optional)
ButtonName: The name of the button press to check for (e.g. "Fire1", etc.) (optional)
ObjectTag: The tag of the GameObject on which the script is located (optional)
ScriptName: The name of the script on the GameObject (optional)
MethodName: The name of the method being called (optional)
Parameter: The parameter to pass to the method (optional)
Disclaimers:
If ObjectTag is empty, the first found script in the scene with the given name is called instead.
If the ScriptName or MethodName are empty, no method is called.
While Parameter is technically of type string, Integers and Floats can also be written, and will be parsed accordingly.
Currently, methods with more than one parameter cannot be called.
LockedChoice
Removes one of a ChoiceNode's choices if some condition is met.
Max Quantity: None
Node Type(s): Choice
Variables:
Actor: A reference to the actor who's variable is being checked
ChoiceNumber: The index of the choice being removed (base 1)
VariableType: The type of the variable being checked (e.g. Statistic, Topic, etc.)
VariableName: The name of the variable being checked
ComparisonType: The type of the comparison being performed against the variable
Comparison: The value to compare the variable against
Log
Prints a Debug.Log to the console.
Max Quantity: None
Node Type(s): Any
Variables:
Message: The message to log
PortraitChange
Changes and actor's portrait.
Max Quantity: None
Node Type(s): Any
Variables:
Actor: A reference to the actor who's portrait is being changed
ChangeType: The change being made to the portrait (set, enabled, or disabled)
PortraitIndex: The index of the portrait to be set (from within the actor's Portraits
Disclaimers:
For a portrait to be set, a Sprite with the corresponding index must be in the DescantActor's Portraits property.
RandomizedChoice
Randomizes/shuffles a ChoiceNode's choices.
Max Quantity: 1
Node Type(s): Choice
Disclaimers:
This Component will automatically always be set to be the last variable, to avoid unintended errors.
RelationshipChange
Changes one of an actor's relationships.
Max Quantity: None
Node Type(s): Any
Variables:
FirstActor: A reference to the actor who's relationship is being checked
SecondActor: A reference to the actor that the relationship corresponds to
OperationType: The change being made to the relationship (increase, decrease, or set)
OperationValue: The value to change the relationship by
Disclaimers:
Changing the first actor's relationship to the second will not change the second's relationship to the first.
StatisticChange
Changes an one of actor's statistics.
Max Quantity: None
Node Type(s): Any
Variables:
Actor: A reference to the actor who's statistic is being changed
StatisticName: The name of the statistic being changed
OperationType: The change being made to the statistic (increase, decrease, or set)
OperationValue: The value to change the statistic by
StatisticReveal
Calls a method from a script, passing it an actor's statistic (e.g. to display how an NPC's mood might increase/decrease during a dialogue).
Max Quantity: None
Node Type(s): Any
Variables:
Actor: A reference to the actor who's statistic is being revealed
StatisticName: The name of the statistic being revealed
ObjectTag: The tag of the GameObject on which the script is located (optional)
ScriptName: The name of the script on the GameObject
MethodName: The name of the method being called
Disclaimers:
If ObjectTag is empty, the first found script in the scene with the given name is called instead.
If the ScriptName or MethodName are empty, no method is called.
Currently, methods with more than one parameter cannot be called.
TimedChoice
Imposes a time restriction for choosing a TimedChoice's choice. Each FixedUpdate frame that the time is counting down, a method from a script can be called, passing the timer completion percentage (e.g. to update a timer UI). When the time reaches 0, a choice is automatically made, and another method can be called (e.g. to initiate a point penalty).
Max Quantity: 1
Node Type(s): Choice
Variables:
Time: The amount of time the player has to choose (in seconds)
ChoiceToPick: The index of the choice to pick if the timer runs out (base 1)
ObjectTag: The tag of the GameObject on which the script is located (optional)
ScriptName: The name of the script on the GameObject
TimerMethodName: The name of the method called while the timer is counting down (optional)
FinishedMethodName: The name of the method called when the timer reaches 0 (optional)
Disclaimers:
If ObjectTag is empty, the first found script in the scene with the given name is called instead.
If the ScriptName is empty, no method is called. If TimerMethodName is empty, that method isn't called. If FinishedMethodName is empty, that method isn't called.
Currently, methods with more than one parameter cannot be called.
TopicChange
Changes one of an actor's topics.
Max Quantity: None
Node Type(s): Response
Variables:
Actor: A reference to the actor who's topic is being changed
TopicName: The name of the topic being changed
ChangeType: The change being made to the topic (add or remove)
Component creation
- Create a new C# class in Descant/Components/Custom.
- Make sure that the Component is in the Descant.Components namespace.
- Make sure that the Component inherits from the DescantComponent abstract class.
- Add a [Serializable] attribute to the Component.
- Add a [MaxQuantity(...)] attribute to the Component (replace the '...' with the maximum number of Components of this type that can be added to a single node) ('...' can be float.PositiveInfinity).
- Add a [NodeType(...)] attribute to the Component (replace the '...' with the DescantNodeType indicating which types of nodes it can be added to).
- Optional: Add a [DontShowInEditor] attribute to the Component to bar it from being added in the Descant Graph Editor.
- Add any number of public variables/properties to the Component (these properties will show up in the Descant Graph Editor when you add the Component to a node) (you may also create private/protected properties, but they won't appear in the editor). Properties may only be of type string, float, int, bool, Vector2, Vector3, Color, UnityEngine.Object (including but not limited to DescantActor), or Enum.
- For each public variable, add either an [Inline] attribute (indicating that it will be visually nestled beside the Component name in the editor) or a [ParameterGroup(...)] attribute (indicating that it will be visually arranged in a new group beneath the Component name in the editor) (replace the '...' with the string name of the group to order it into).
- Optional: By default, all Component fields filter any out most special characters on input. You can override this by giving any public variable a [NoFiltering] attribute, disabling filtering for that variable's corresponding field in the Descant Graph Editor. This is useful for long-form fields that may have sentence grammar and punctuation.
- If this Component performs some action when it is reached during dialogue, give it the following method: public override DescantNodeInvokeResult Invoke(DescantNodeInvokeResult result). The DescantNodeInvokeResult object being passed contains all the choice/response text for the current node, the current actors, and info regarding the actor portraits) (see the DescantNodeInvokeResult class for more info). The Invoke method must return a DescantNodeInvokeResult object (almost always just result itself, with its properties modified).
- Optional: Many default Descant Components only do their effect if some comparison is made. Should your Component also wish to do so, the CompareVariable method in DescantComponentUtilities may be of use.
- Optional: If you need the Component to do something continuously while it is active during dialogue, give it one of the following methods: public override bool FixedUpdate() or public override bool Update(). They function in exactly the same manner as the classic MonoBehaviour methods of the same names, save for the fact that if they ever return false, the dialogue ends immediately (should the Component want to end the dialogue for some reason).
- That's it! Your new Component will now show up as an option to add to a node in the Descant Graph Editor.