Aller au contenu

Barks

Les barks sont de courtes répliques ponctuelles qu'un PNJ lance de lui-même — un bonjour au passage, un commentaire d'ambiance, une réaction à votre proximité. Dans Libretto, un bark n'est qu'un petit fragment de dialogue joué par le runtime habituel, avec une particularité : au lieu de jouer ses répliques dans l'ordre, le sous-dialogue choisit une réponse au hasard à chaque démarrage.

Cette page explique comment créer un sous-dialogue de barks aléatoires, comment le déclencher depuis le gameplay, et comment les systèmes intégrés d'anti-répétition et de priorité de dialogue empêchent les barks d'empiéter sur vos scènes importantes.

Le flag RandomBarks

Vous transformez un sous-dialogue ordinaire en source de barks en levant un seul flag dessus. Dans la section Subdialogue Details ▸ Flags, ajoutez le tag :

Libretto.Flags.Subdialogue.Staging.RandomBarks

Une fois ce flag posé, le sous-dialogue ne se joue plus de haut en bas. À son démarrage, Libretto choisit l'une de ses lignes Reply au hasard et ne joue que le contenu situé sous cette réponse.

The RandomBarks flag on a subdialogue

Note

Le flag est exposé sous forme de la constante C++ TAG_LBRSubDialogueFlag_RandomBarks. Le runtime le vérifie avec Subdialogue->HasFlag(...) avant d'emprunter le chemin de tirage aléatoire — un sous-dialogue sans ce flag se joue toujours normalement.

Structure d'un sous-dialogue de barks

Le flag RandomBarks attend une forme précise : un unique Choice au sommet, avec une Reply par bark en dessous. Chaque réponse contient le contenu réel du bark.

ID Type Texte
— Choice (racine)
— Reply
— — Hello!
— Reply
— — How are you?
— Reply
— — You can talk to me by walking into the trigger.

Un bark n'a pas à se limiter à une seule ligne. Comme chaque réponse est une branche de dialogue ordinaire, un bark peut comporter une ou plusieurs lignes et impliquer plus d'un personnage — ce n'est qu'un fragment de dialogue en forme libre. À l'exécution, exactement une réponse est tirée et jouée intégralement.

A Choice-plus-Replies barks subdialogue

Chaque ligne possède toujours un Speaker (et une émotion/posture) comme d'habitude. Sur les lignes Reply, vous voudrez souvent utiliser Do Once, Display Condition et Availability Condition — les mêmes options de réponse décrites dans le Dialogue Editor — pour conditionner certains barks à l'état du jeu.

Tip

Les ID de ligne d'un sous-dialogue sont des identifiants internes stables, pas un ordre de lecture — ils peuvent sembler non séquentiels (0, 1, 2, 7, 9, 8, 10). Le tirage aléatoire se base sur le type de ligne, si bien que les ID n'ont ici aucune importance.

Jouer les barks — StartGenericDialogue

Les barks sont généralement déclenchés en tant que dialogues génériques : des instances jetables sans caméras ni animations pré-bakées, instanciées à la demande et détruites une fois la réplique terminée. Le point d'entrée est le nœud statique et Blueprint-callable Start Generic Dialogue (ALBRDialogueInstance::StartGenericDialogue).

Vous lui fournissez :

  • l'asset Dialogue contenant votre sous-dialogue de barks,
  • une spawn transform (l'endroit d'où le bark est joué),
  • un sélecteur de sous-dialogue optionnel — le tag qui choisit le sous-dialogue de barks lorsque l'asset en contient plusieurs.

Pour les variantes pilotées par sélecteur, utilisez Start Generic Dialogue With Selector / …With Selectors / …With Selector Query (StartGenericDialogueWithSelector, StartGenericDialogueWithSelectors, StartGenericDialogueWithSelectorQuery). Celles-ci apparient le sous-dialogue par ses tags Selectors (définis dans Subdialogue Details), plutôt que par le premier sous-dialogue jouable.

The Start Generic Dialogue node and its selector pins

Un motif de démo courant est un timer qui redéclenche le bark toutes les quelques secondes : chaque appel tire une nouvelle réponse aléatoire, et le système de priorité (ci-dessous) écarte discrètement l'appel dès qu'un dialogue plus important est déjà en cours.

Acteur barker de la showcase

La showcase de Libretto est livrée avec un acteur de démonstration tout prêt, ALBRShowcaseBarker (dans le plugin Libretto), qui pilote les barks de deux façons depuis un volume de proximité :

  • Mode timer (bBarkOnTimerWhileNear) — tant que le pawn du joueur est à l'intérieur du volume, un bark se déclenche toutes les BarkInterval secondes.
  • Mode interaction (bBarkOnPlayerOverlap) — un seul bark se déclenche lorsque le joueur entre dans le volume, limité par InteractionCooldown. Vous pouvez aussi en déclencher un manuellement depuis le Blueprint via TriggerBark().

Pointez son BarkDialogue vers un dialogue dont le sous-dialogue porte le flag RandomBarks, définissez éventuellement un SubdialogueSelector, et il achemine chaque bark via StartGenericDialogueWithSelector.

The showcase barker actor

Anti-répétition

Par défaut, Libretto ne joue pas deux fois de suite le même bark. Après le tirage d'une réponse, celle-ci est enregistrée afin que le tirage suivant l'ignore.

L'historique est stocké dans le sous-système GPVar sous le runtime tag Libretto.RuntimeFlags.BarkHistory, avec pour clé le tag du sous-dialogue plus le tag de la réponse. Lorsqu'un sous-dialogue s'apprête à tirer, chaque réponse candidate passe par CanPlayRandomBark, qui renvoie false pour la réponse enregistrée comme dernière jouée ; après qu'un bark a été joué, MarkBarkPlayed inscrit la nouvelle réponse dans l'historique.

Par conception, seul le bark le plus récent est mémorisé — assez pour éviter une répétition immédiate, mais pas pour garantir une plus longue série sans répétition.

Historique personnalisé

CanPlayRandomBark et MarkBarkPlayed sont tous deux des BlueprintNativeEvents sur ALBRDialogueInstance. Sous-classez votre instance de dialogue (en Blueprint ou en C++) et surchargez-les pour implémenter un historique plus riche — ne jamais répéter un bark tant que tous n'ont pas été épuisés, pondérer les choix, mémoriser plusieurs tirages en arrière, etc. Voir GPVars pour le stockage sous-jacent.

Barks et priorités de dialogue

Vous pouvez conserver un sous-dialogue de barks dans un asset de dialogue qui contient aussi de « vraies » conversations, mais gardez deux contraintes à l'esprit :

  • Un personnage ne peut être que dans un seul dialogue à la fois. Un bark et une scène importante qui partagent un personnage se disputeront le créneau de dialogue de ce personnage.
  • Cette dispute est arbitrée par les priorités de dialogue, et non par un verrou strict. Lorsqu'un bark tente de démarrer alors qu'un dialogue de priorité supérieure est déjà en cours avec un personnage commun, le système de priorité ignore simplement le bark — le timer continue de se déclencher, mais rien ne se joue jusqu'à la fin de la scène.

C'est exactement ce que vous voulez : les barks d'ambiance meublent l'espace, puis s'effacent dès que quelque chose d'important commence. Donnez aux barks une Dialogue Priority basse et à vos scènes clés une priorité plus élevée. Voir Dialogue Priorities pour le modèle d'arbitrage complet (Play / Interrupt / Ignore / Muffle / Mute).

Tip

Si des barks et un dialogue important entrent sans cesse en collision sur le même PNJ — par exemple des PNJ de foule murmurant derrière une scène scriptée — séparez-les en assets de dialogue distincts afin que leurs listes de personnages ne se chevauchent jamais.

Sous-titres 3D pour les barks

Comme un bark est prononcé dans le monde plutôt que dans une conversation cadrée, vous voudrez souvent que son sous-titre flotte au-dessus du locuteur plutôt que sur le HUD 2D.

Flag Subtitle3D

Ajoutez le line flag Libretto.Flags.Lines.Subtitle3D à une ligne de bark pour afficher son sous-titre en espace monde, au-dessus du locuteur, à la manière d'un bark, plutôt que sur le HUD 2D. À l'exécution, ULBRDialogueManager attribue à chaque ligne portant ce flag un widget en espace monde au-dessus de son locuteur, qui a priorité sur le sous-titre du HUD pour cette ligne. Positionnez-le sur les lignes Text/Reply de votre sous-dialogue de barks.