Table of Contents

Dialogue Actions

Actions, sometimes referred to as events, are executed through a node's event. Actions can be executed either on the start or end of the node.

Start of the node is defined as the first time the processor for that node is called. The end of a node is defined as the first time the processor for the next node is called

Note

Start actions are ran after pre processors but before the node is processed.

Creating A Custom Action (Event)

Actions are treated similarly to dialogue nodes. They require a node, data and a processor.

The node needs to inherit from DialogueBlockNode<T> where T is of type DialogueNodeData. Processors are created in the same manner except that the bool CanProgressNode(ConversationNodeData nodeData, DialogueDirector director) function is never called. This is also true for void HandleCancellation(ConversationNodeData nodeData, DialogueDirector director).

In this example we will create the default AudioNode from scratch.

First we need a data class

[Serializable]
public class AudioNodeData : BlockNodeData
{
    public AudioClip audioClip;
}

Then create the action

[Serializable, UseWithContext(typeof(ActionNode)), Node("Events", "", "Audio Player")]
public class AudioNode : DialogueBlockNode<AudioNodeData>
{
    public override bool SupportStartAction => false;
    public override bool SupportEndAction => false;
    
    public const string IN_AUDIOCLIP = "AudioClip";
    
    public override AudioNodeData ProcessNodeAsset(DialogueGraph graph, Dictionary<IPort, int> portmap) => new()
    {
        audioClip = GetPortValue<AudioClip>(GetInputPortByName(IN_AUDIOCLIP))
    };
    
    protected override void OnDefinePorts(IPortDefinitionContext context) => context.AddInputPort<AudioClip>(IN_AUDIOCLIP).Build();
}

Since it is a BlockNode, it needs to be used within a ContextNode. As such the [UseWithContext] attribute is required with the type ActionNode.

Tip

Unless expressed disabled, action nodes can have actions linked to them

Finally, we need the processor

public class AudioProcessor : DialogueProcessor<AudioNodeData>
{
    [SerializeField] AudioSource audioSource;
    
    protected override void ProcessNode(AudioNodeData nodeData, DialogueDirector director)
    {
        audioSource.clip = nodeData.audioClip;
        audioSource.Play();
    }
}