Articy:Draft sample integration

This script shows one way in which articy:draft flows can be made to work with AC's dialogue and conversation system. It is able to display articy speech and conversation trees in AC.

NOTE: For a thorough and robust link between AC and articy:draft, try Dialogue System on the Asset Store.

To use this script, paste it in a C# file named **ArticyFlowIntegration**, attach it to an Articy Flow Player component in your scene (provided by articy's own Unity integration package), and invoke its **RunFlow()** method to run it.

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Articy.Unity;
using Articy.Unity.Interfaces;

namespace AC
{

 [RequireComponent (typeof (ArticyFlowPlayer))]
 public class ArticyFlowIntegration : MonoBehaviour, IArticyFlowPlayerCallbacks
 {

 public IArticyObject startObject;

 private ArticyFlowPlayer articyFlowPlayer;
 private Branch autoRunBranch;
 private Speech currentSpeech;
 private IList<Branch> conversationBranches;
 private Conversation conversation;

 private NPC[] npcs;
 private bool isRunning;
 private bool isPaused;

 private void OnEnable ()
 {
 // Hook into the OnClickConversation event, which we'll use to handle conversation clicks
 EventManager.OnClickConversation += OnClickConversation;

 // Assign and disable the ArticyFlowPlayer component until we're ready for it
 articyFlowPlayer = GetComponent <ArticyFlowPlayer>();
 articyFlowPlayer.enabled = false;

 // Get a collection of NPCs to refer to later
 npcs = FindObjectsOfType <NPC>();
 }

 private void OnDisable ()
 {
 // Unhook from the OnClickConversation event
 EventManager.OnClickConversation -= OnClickConversation;
 }

 private void Update ()
 {
 if (isPaused)
 {
 UpdateFlow ();
 }
 }

 // Call this function externally to run the ArticyFlowPlayer
 public void RunFlow ()
 {
 // Place the game into scripted-cutscene mode
 KickStarter.stateHandler.EnforceCutsceneMode = true;

 // Make sure a Conversation component is attached, and is set to rely on script for its interactions
 if (conversation == null)
 {
 conversation = gameObject.AddComponent <Conversation>();
 }
 conversation.interactionSource = InteractionSource.CustomScript;

 // Enable the ArticyFlowPlayer component
 articyFlowPlayer.enabled = true;
 isRunning = true;

 // Record the StartOn IArticyObject, or restore it if this has already been played once
 if (startObject == null)
 {
 startObject = articyFlowPlayer.StartOn;
 }
 else
 {
 articyFlowPlayer.StartOn = startObject;
 }
 }

 private void UpdateFlow ()
 {
 // Wait for no Speech or Conversation to be active
 if ((currentSpeech == null || !currentSpeech.isAlive) && KickStarter.playerInput.activeConversation == null)
 {
 currentSpeech = null;

 if (autoRunBranch != null)
 {
 // Play the next branch automatically
 articyFlowPlayer.Play (autoRunBranch);
 }
 else if (conversationBranches != null)
 {
 // Show the branches as a Conversation
 conversation.Interact ();
 }
 else if (KickStarter.playerInput.activeConversation == null)
 {
 // Can't find anything else to run, so stop the flow
 StopRunning ();
 }
 }
 }

 public void OnFlowPlayerPaused (IFlowObject aObject)
 {
 if (aObject is IDialogue)
 {
 articyFlowPlayer.Play ();
 return;
 }

 isPaused = true;
 currentSpeech = null;

 // Check for a speaking character
 var dlgSpeaker = aObject as IObjectWithSpeaker;
 if (dlgSpeaker != null)
 {
 Sprite portraitGraphic = null;
 string displayName = "";
 string speechText = "";

 // Grab the speaker's portrait graphic
 if (dlgSpeaker.Speaker != null)
 {
 IAsset speakerAsset = ((dlgSpeaker.Speaker as IObjectWithPreviewImage).PreviewImage.Asset as IAsset);
 if (speakerAsset != null)
 {
 portraitGraphic = speakerAsset.LoadAssetAsSprite ();
 }
 }

 // Grab the speaker's name
 var modelWithDisplayName = aObject as IObjectWithDisplayName;
 if (modelWithDisplayName != null)
 {
 displayName = modelWithDisplayName.DisplayName;
 }

 // Assign the portrait graphic and name to the correct AC character
 Char speaker = GetCharacterWithName (dlgSpeaker.Speaker.TechnicalName);
 if (speaker != null)
 {
 if (!string.IsNullOrEmpty (displayName))
 {
 speaker.speechLabel = displayName;
 }
 if (portraitGraphic != null && portraitGraphic.texture != null)
 {
 speaker.portraitIcon.texture = portraitGraphic.texture;
 }
 }

 // Extract the dialogue text and play it in AC
 var txtObj = aObject as IObjectWithText;
 if (txtObj != null)
 {
 speechText = txtObj.Text;
 currentSpeech = KickStarter.dialog.StartDialog (speaker, speechText);
 }
 }
 }

 public void OnBranchesUpdated (IList<Branch> aBranches)
 {
 conversationBranches = null;
 autoRunBranch = null;

 if (aBranches.Count == 1)
 {
 // Only one branch, so prepare to run it automatically
 autoRunBranch = aBranches[0];
 }
 else if (aBranches.Count > 1)
 {
 // Multiple branches, so prepare them as a Conversation
 conversationBranches = aBranches;

 conversation.interactionSource = InteractionSource.CustomScript;
 conversation.options.Clear ();
 for (int i=0; i<aBranches.Count; i++)
 {
 string optionText = "Option " + i.ToString ();

 var obj = aBranches[i].Target as IObjectWithMenuText;
 if (obj != null)
 {
 optionText = obj.MenuText;
 }

 ButtonDialog buttonDialog = new ButtonDialog (i, optionText, true);
 conversation.options.Add (buttonDialog);
 }
 }
 }

 private void StopRunning ()
 {
 if (isRunning)
 {
 // End the flow, and exit scripted-cutscene mode

 isRunning = false;
 articyFlowPlayer.enabled = false;
 conversationBranches = null;
 currentSpeech = null;

 KickStarter.stateHandler.EnforceCutsceneMode = false;
 }
 }

 private void OnClickConversation (Conversation \_conversation, int optionID)
 {
 if (conversation == \_conversation)
 {
 // Run the Branch if the object's own Conversation component was interacted with

 KickStarter.playerInput.EndConversation ();
 articyFlowPlayer.Play (conversationBranches[optionID]);
 conversationBranches = null;
 }
 }

 private Char GetCharacterWithName (string technicalName)
 {
 if (!string.IsNullOrEmpty (technicalName))
 {
 foreach (NPC npc in npcs)
 {
 if (npc.gameObject.name == technicalName)
 {
 return npc;
 }
 }

 if (KickStarter.player && KickStarter.player.gameObject.name == technicalName)
 {
 return KickStarter.player;
 }
 }
 return null;
 }

 public bool IsRunning
 {
 get
 {
 return isRunning;
 }
 }

 }

}

```

Additionally, this script allows for your articy project's language to be automatically synced with AC's language:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Articy.Unity;

namespace AC
{

 public class ArticyLanguageSync : MonoBehaviour
 {

 public string[] languageNames;

 private void OnEnable ()
 {
 EventManager.OnChangeLanguage += OnChangeLanguage;
 OnChangeLanguage (Options.GetLanguage ());
 }

 private void OnDisable ()
 {
 EventManager.OnChangeLanguage -= OnChangeLanguage;
 }

 private void OnChangeLanguage (int index)
 {
 if (languageNames != null && languageNames.Length > index)
 {
 string languageName = languageNames[index];
 ArticyDatabase.Localization.Language = languageName;
 ACDebug.Log ("Articy:Draft - changed language to " + languageName, this);
 }
 else
 {
 ACDebug.LogWarning ("Articy:Draft - cannot change language because languageNames does not have " + (index+1) + " elements.", this);
 }
 }

 }

}

```