Skip to main content
Version: 0.15.0

Bark Service

Description

Decides when agents bark, picks what they say, and hands the line to presentation and audio. Everything it plays through is behind an interface, so any part can be replaced or added to. See Barks for how barks are authored.

Every service is registered with the module system. Get one with:

csharp
var barks = ModuleInitializer.GetService<IBarkService>();

IBarkService

NameParametersReturn TypeDescription
SourcesN/AIReadOnlyList<IBarkSource>Where barks come from, in the order they're asked.
AddSourceIBarkSource sourcevoidAdds a source after the others.
InsertSourceint index, IBarkSource sourcevoidAdds a source at a position. 0 is asked first.
RemoveSourceIBarkSource sourceboolRemoves a source.
TryBarkIAgentService agentboolGives the agent its regular chance to bark. True if a bark started.
BarkIAgentService agent, BarkData bark, bool ignoreCooldowns = falseboolMakes the agent say a specific line now. Still gives way to conversations and blocks.
CancelIAgentService agentvoidStops the agent's current bark.
CancelAllN/AvoidStops every bark.
IsBarkingIAgentService agentboolWhether the agent is barking.

To make an agent bark from your own code, for example when it spots the player:

csharp
ModuleInitializer.GetService<IBarkService>()?.Bark(agent, spottedLine);

IBarkSource

Somewhere a bark can come from. Sources are asked in order and the first to offer a collection is used. The General bank is added as the last source.

NameParametersReturn TypeDescription
FindCollectionIAgentService agentBarkCollectionThe collection this agent should bark from, or null to pass it on.

Insert your own source at index 0 to take priority over the General bank.

IBarkAvailabilityCheck

A veto on an agent starting a bark. Every check is asked, and any one returning false stops the bark. This is the bark version of IConversationAvailabilityCheck.

NameParametersReturn TypeDescription
CanBarkIAgentService agentboolFalse to stop this agent barking.

Register your own with RegisterMulti<IBarkAvailabilityCheck> in your module registrar. They sit alongside NodeBarkBlockPolicy, which applies the Block Barks option on behaviour tree nodes.

IBarkPresentationService

Shows a bark's text.

NameParametersReturn TypeDescription
PresentIAgentService agent, string text, float durationvoidShows the text and hides it after the duration.
CancelIAgentService agentvoidHides the agent's text now.
CancelAllN/AvoidHides all bark text.
ImplementationUsed when
WorldTextBarkPresentationServiceCIVIL-DIALOGUE-SYSTEM isn't installed.
DialogueBarkPresentationServiceCIVIL-DIALOGUE-SYSTEM is installed. Uses its overhead text bubble.
NoOpBarkPresentationServiceCIVIL-DIALOGUE-SYSTEM isn't installed and Show Text is off, or TextMeshPro's essential resources are missing.

IBarkAudioResolver

Chooses which clip an agent plays for a line. The default returns the line's own clip. Replace it to give agents different voices for the same line, using the line's id.

NameParametersReturn TypeDescription
ResolveIAgentService agent, string lineId, AudioClip fallbackClipAudioClipThe clip to play, or null.

A line's id is fixed when the line is created and doesn't change if the asset is renamed. Read it with BarkData.GetLineId().

IBarkAudioPlayer

Plays bark audio.

NameParametersReturn TypeDescription
ActiveCountN/AintHow many bark clips are playing. Used for the audio limit.
PlayIAgentService agent, AudioClip clip, float pitchvoidPlays the clip from the agent.
StopIAgentService agentvoidStops the agent's bark clip.
StopAllN/AvoidStops every bark clip.

The default, AgentAudioSourceBarkPlayer, plays through an Audio Source on the agent and never changes that Audio Source's assigned clip, so it can share one with dialogue.

Replacing a default

The Civil AI module registers the bark service when modules register, and registers the presenter, audio player and audio resolver later, when modules initialise, but only if nothing is registered for them yet. To use your own, register it in your module registrar's Register method:

csharp
public void Register(IServiceRegistry registry, ModuleBootstrapContext context)
{
registry.TryRegisterSingleton<IBarkAudioResolver>(ModuleId, new VoiceBankResolver());
}

Every module finishes registering before any module initialises, so yours is in place first and the default is skipped.