Dialogue Director 2.4.0 — C++ API
Review draft. This source page has not completed website editorial and release-specific verification.
Dialogue Director is a standalone Unreal Engine 5.7 plugin. Runtime state belongs to the GameInstance-scoped UDialogueDirectorSubsystem. Public Runtime APIs are under DialogueDirectorRuntime; graph authoring and interchange APIs are under DialogueDirectorEditor.
Core runtime
Section titled “Core runtime”Include DialogueDirectorSubsystem.h for conversation lifecycle and session controls. Begin a session with FDialogueConversationStartRequest, then inspect the returned FDialogueConversationStartResult status before presenting UI. The focused Line and Choice APIs return structured presentation and continuation results. All state mutation and traversal occur on the game thread.
Dialogue 2.4.0 adds GetActiveSessionId(), which returns the transient FGuid for an active conversation and an invalid Guid when none is active. OnPresentationChanged carries only that ID; after the callback, query GetActiveConversationSession, GetCurrentLinePresentation, GetCurrentLineDeliveryPresentation, or GetCurrentChoicePresentation for current authoritative state. It fires after committed Dialogue-owned session, node/frame, effective participant-binding, and applicable choice-history/retry changes. No-op node updates and retry resets that already have no state return do not emit duplicate notifications. OnSessionEnded carries the ended ID after active state and identity are cleared, so callbacks observe no active session. The ID is transient and is not part of runtime snapshots.
Optional event-driven consumers should take an initial snapshot, refresh on these events, and refresh after accepted Dialogue commands. They may bind an explicit invalidation source when an external condition, skill, or resolution provider exposes one. Dialogue cannot detect silent internal provider changes and does not poll per frame. This contract has no UI Director or DirectorBridge types.
Participant bindings resolve authored role names or stable role identities against the current frame. SubDialogue maps a callee role explicitly to an immediate caller role. Dialogue does not infer participant roles from player or speaker conventions.
Neutral resolution
Section titled “Neutral resolution”IDialogueResolutionProvider in Resolution/DialogueResolutionProvider.h is the sole external resolution contract. It has ResolveCheck and SelectWeighted operations. Register one native provider per GameInstance:
FDialogueResolutionProviderRegistrationResult Registration = DialogueSubsystem->RegisterResolutionProvider(ProviderId, Provider);if (Registration.IsSuccess()){ // Retain Registration.Handle for exact-owner removal.}Remove it using UnregisterResolutionProvider with the exact FDialogueResolutionProviderHandle. Provider registration is native-only and has no Blueprint registration API.
FDialogueCheckDefinition authors ResolutionProfileId, ValueSourceKey, BaseValue, optional SkillId and SkillParticipantRoleId, comparison, target and range end, ordered scalar inputs, and success/failure outcome IDs. A Skill source is acquired through the optional Dialogue Skill query service before neutral dispatch. Retry policy and reset-condition identity live on FDialogueCheckNodePayload.
FDialogueResolutionIdentity preserves DialogueId, ContextKey, OperationId, ActivationScope, OperationKind, and AttemptIndex. FDialogueCheckResult contains only Dialogue-owned status, outcome, outcome ID, identity, graph routing identity, and attempt index. It contains no raw sample, die result, rules object, or provider-specific diagnostic.
When no provider is registered, ResolveCheckWithProvider and SelectWeightedWithProvider report ProviderUnavailable. Production Check, RandomBranch, and weighted Dialogue Set operations use this same provider contract and have no local fallback.
Blueprint check API
Section titled “Blueprint check API”UDialogueDirectorCheckLibrary exposes IsValidCheckOutcomeId, IsValidCheckDefinition, and EvaluateCheck. EvaluateCheck resolves only through the native provider registered for the WorldContextObject’s GameInstance. It returns FDialogueCheckResult and reports provider absence explicitly.
Persistence
Section titled “Persistence”FDialogueRuntimeSnapshotCodec exposes EncodeRuntimeSnapshot and DecodeRuntimeSnapshot. DialoguePersistenceFormatVersion is 3. The snapshot preserves owner-owned history, check retry state, active frame identity, activation scopes, and NextActivationOrdinal. It stores no provider object, participant UObject, or external mechanics state. SaveGame ContributorSchema remains owned by the optional SaveGame integration and is unchanged at 1.
Conditions, actions, events, and extensions
Section titled “Conditions, actions, events, and extensions”Native external Action routes (Dialogue 2.2.0)
Section titled “Native external Action routes (Dialogue 2.2.0)”Include Execution/DialogueExternalActionRoute.h and implement IDialogueExternalActionRoute with an ordinary native C++ class. It has no UCLASS, UINTERFACE, UObject ownership, or UHT-generated declarations. Register a shared instance for one exact authored Action Tag:
FDialogueExternalActionRouteRegistrationResult Registration = Dispatcher->RegisterNativeExternalActionRoute(ActionTag, NativeRoute);if (Registration.IsSuccess()){ // Retain Registration.Handle and pass it to UnregisterNativeExternalActionRoute.}The dispatcher belongs to a GameInstance. The tag is the existing generic FGameplayTag Action route identity; it is not serialized again. Each registration returns an FDialogueExternalActionRouteHandle containing that tag and a unique token. A tag already owned by either a native route or a reflected handler conflicts; different tags can register independently. Unregister requires the current handle, and dispatcher shutdown releases all registered shared routes.
ExecuteDialogueActionBatch(UGameInstance&, const FDialogueActionBatchExecutionRequest&) receives the owning GameInstance and the unchanged Dialogue request: DialogueId, ContextKey, node ID, and generic authored Action definitions including ActionId, ActionTag, label, execution settings, and opaque FInstancedStruct payload. The request does not expose resolved participant object bindings; integrations resolve their own owner data from semantic payload roles through their own services. Calls occur on the GameInstance’s game thread.
Within the default GameInstance dispatcher, an exact registered native route takes precedence for that tag. If there is no native route, the current reflected UObject route is used. The dispatcher preflights route availability, then invokes contiguous same-handler batches in authored order and stops on the first failure. It performs no cross-route rollback: successful earlier route segments remain committed. Native handlers return the existing FDialogueActionBatchExecutionResult, including status and FailedActionId.
DispatchDialogueActionAsync may be overridden for FireAndContinue or WaitForCompletion; its request includes the existing Dialogue completion handle. The default implementation executes synchronously and maps the result the same way as a legacy synchronous handler. The legacy reflected IDialogueRuntimeExecutionRouter and async-router path remain supported. An explicit per-step ExecutionRouter continues to override selection of the default GameInstance dispatcher.
The registration contract is Runtime-native and not exposed to Blueprint. It adds no authored or serialized Action data and no Editor module dependency. Optional integration modules can keep their implementation source in owner-free distributions and compile it only where Dialogue’s public Runtime header is available. Runtime extension contracts include IDialogueExternalConditionResolver, IDialogueRuntimeExecutionRouter, IDialogueRuntimeAsyncExecutionRouter, IDialogueRuntimeEventSink, and the native external-condition resolver. Their registrations are scoped to their GameInstance dispatchers. Exact tokens or owner identities govern removal.
Skill query and mutation service interfaces are optional integration seams. Dialogue stores no Skill values. Quest, World State, Character State, Inventory, Knowledge, Relationship, SaveGame, and SignalBus integrations remain in their owner bridges.
Editor and interchange
Section titled “Editor and interchange”DialogueDirectorEditor contains the graph model, generic Check authoring, search and copy/paste, validation, preview, localization tools, and typed interchange. DialogueDefinition interchange schemaVersion is 3. Import is typed and transactional; obsolete schema versions are rejected. CSV is a constrained projection over canonical document.json.
Resolution Editor provider
Section titled “Resolution Editor provider”Optional integrations may implement IDialogueResolutionEditorProvider from Resolution/DialogueResolutionEditorProvider.h in DialogueDirectorEditor. Register one TSharedRef with FDialogueResolutionEditorProviderRegistry::Get().RegisterProvider; retain the returned FDialogueResolutionEditorProviderRegistrationResult::Handle and pass that exact handle to UnregisterProvider during module shutdown. Re-registering the same provider instance is idempotent; a different active provider conflicts. The registry holds the active provider strongly and clears it when DialogueDirectorEditor shuts down.
The provider may return FDialogueResolutionEditorProfileDescriptor values through GetProfileDescriptors, validate FDialogueResolutionEditorValidationRequest and return FDialogueResolutionEditorValidationResult, append a generic Check summary through BuildCheckSummary, gather terms through GatherCheckSearchTerms, and handle FDialogueResolutionEditorPreviewRequest by returning FDialogueResolutionEditorPreviewResult with ordered FDialogueResolutionEditorPreviewField values. Profile descriptors are display-only. Duplicate and invalid IDs are diagnosed and omitted. The authored Check continues to store only FDialogueResolutionProfileId.
Without a provider, profile IDs remain editable and owner structural validation continues normally. Provider validation is presented separately and does not affect Dialogue structural validity. Provider summaries cannot replace the base semantic summary. Preview is synchronous, read-only, transient, and non-authoritative; Unavailable or Error preview results do not invalidate authoring. This Editor API is not visible to DialogueDirectorRuntime and does not register a Runtime resolution provider.
Other optional external authoring providers implement the generic Dialogue Editor authoring interface in the Editor module. The base Editor does not depend on DirectorBridge or Probability Director.
Optional Probability integration
Section titled “Optional Probability integration”Dialogue Director has no direct dependency on Probability Director or DirectorBridge. Projects that want Probability mechanics may install DirectorBridge Dialogue.Probability ContractVersion 3, which implements IDialogueResolutionProvider and owns the mechanics-to-profile mapping. Without it, resolution-dependent operations return ProviderUnavailable.