Skip to main content

Custom Audio Provider

If you are using an audio engine other than Unity AudioSource, FMOD, or Wwise — or if you need behaviour that the built-in providers do not cover — you can implement IConvoAudioProvider yourself.


The Interface

public interface IConvoAudioProvider
{
void PlayVoiceLine(ConvoCoreConversationData.DialogueLineInfo line, ConvoAudioReference reference);
void StopVoiceLine();
void PauseVoiceLine();
void ResumeVoiceLine();
bool IsPlaying { get; }
}

Implement this interface on a MonoBehaviour and attach it to the same GameObject as your ConvoCore runner.


What Each Member Does

PlayVoiceLine(line, reference)

Called by ConvoCore when it is ready to play the audio for a dialogue line. The line argument is the full DialogueLineInfo, giving you access to LineID, characterID, expression data, and anything else from the dialogue data. The reference argument is the resolved audio reference from the manifest.

Depending on the backend you select on the manifest, reference will be one of:

BackendReference typeWhat to cast to
UnityAudioSourceConvoCoreUnityAudioReferenceCast and read .Clip
FMODConvoCoreAudioEventKeyReferenceCast and read .EventKey (FMOD event path)
WwiseConvoCoreAudioEventKeyReferenceCast and read .EventKey (Wwise event name)
CustomWhatever you assigned to the manifest entry's Clip, Key, or Reference slotCast appropriately

For the Custom backend, if you assigned a ConvoAudioReference ScriptableObject subclass to the entry's Ref slot, that subclass instance is passed as reference. If you only filled in the Key text field, a ConvoCoreAudioEventKeyReference is passed.

StopVoiceLine()

Called when:

  • The conversation is stopped via StopConversation().
  • The player skips a line while audio is playing.
  • The player reverses to a previous line.

Immediately stop any currently playing audio.

PauseVoiceLine() / ResumeVoiceLine()

Called when PauseConversation() and ResumeConversation() are invoked on the runner. Pause and resume playback of the current voice line.

IsPlaying

Return true while audio is actively playing, false otherwise. ConvoCore polls this property once per frame during AudioComplete progression. When it transitions to false, ConvoCore advances to the next line.

tip

If your audio engine fires a callback when playback ends (like Wwise's AK_EndOfEvent), use the callback to set a backing bool field and return that field from IsPlaying. This is more reliable than polling an engine-side state that may have race conditions.


Minimal Example

This example plays a AudioClip via a custom AudioSource configuration but also logs every line to a transcript system:

using UnityEngine;
using WolfstagInteractive.ConvoCore;

[AddComponentMenu("ConvoCore/Audio/MyCustomAudioProvider")]
public class MyCustomAudioProvider : MonoBehaviour, IConvoAudioProvider
{
[SerializeField] private AudioSource _voiceSource;

public bool IsPlaying => _voiceSource != null && _voiceSource.isPlaying;

public void PlayVoiceLine(ConvoCoreConversationData.DialogueLineInfo line, ConvoAudioReference reference)
{
if (_voiceSource == null) return;

// Handle a Unity clip reference
if (reference is ConvoCoreUnityAudioReference unityRef && unityRef.Clip != null)
{
_voiceSource.Stop();
_voiceSource.clip = unityRef.Clip;
_voiceSource.Play();
}

// Log to a custom transcript system
MyTranscriptSystem.Record(line.LineID, line.characterID);
}

public void StopVoiceLine() => _voiceSource?.Stop();
public void PauseVoiceLine() => _voiceSource?.Pause();
public void ResumeVoiceLine() => _voiceSource?.UnPause();
}

Using a Custom ConvoAudioReference

If you need to store additional metadata per line (e.g. a subtitle delay offset, a subtitle speaker colour, or a middleware reference type that ConvoCore does not know about), subclass ConvoAudioReference:

using UnityEngine;
using WolfstagInteractive.ConvoCore;

[CreateAssetMenu(menuName = "ConvoCore/Audio/My Audio Reference")]
public class MyAudioReference : ConvoAudioReference
{
public AudioClip Clip;
public float SubtitleDelaySeconds;
public Color SpeakerColour = Color.white;
}

Assign instances of this ScriptableObject to the Ref slot of manifest entries when using the Custom backend. In your provider, cast reference to MyAudioReference to access the extra fields.


Injecting a Provider at Runtime

If your provider is instantiated through code rather than added in the inspector, use SetAudioProvider:

var provider = GetComponent<MyCustomAudioProvider>();
_convoCoreRunner.SetAudioProvider(provider);

This overrides any provider assigned via the inspector Audio Provider Object field.


The Custom Backend

Set the manifest's Audio Backend to Custom to show all three assignment slots in the inspector for each entry row:

SlotPurpose
ClipAn AudioClip. Passed as a ConvoCoreUnityAudioReference if no Reference is assigned.
KeyAn arbitrary string. Passed as a ConvoCoreAudioEventKeyReference.
RefA ConvoAudioReference subclass ScriptableObject. Passed directly if assigned; takes priority over Clip and Key.

Your provider decides which of these to use. You can use all three, ignore some, or combine them.


Checklist

Before going live with a custom provider, verify these behaviours:

  • IsPlaying returns false immediately if PlayVoiceLine is called with a null or invalid reference (not stuck at true).
  • StopVoiceLine does not throw if called when nothing is playing.
  • PauseVoiceLine followed by ResumeVoiceLine resumes from the same position (not from the beginning).
  • IsPlaying transitions to false within one frame of playback ending, so AudioComplete lines do not stall.
  • The provider cleans up any temporary objects or unmanaged resources it creates during PlayVoiceLine.