Forum rules - please read before posting.

Script importer/converter to AC?

edited March 2019 in Engine development

Being able to write all of the dialogue in text, without having to make a new node for every line of dialogue, then importing it into AC, where it then takes your script and turns it into an actionlist that can be dropped into a scene, would save a ton of time for text heavy games.

Even if you had to write your script in special format, it would still save so much time and make editing so much easier.

Comments

  • Since AC's API is all open, such a script can be written on top of AC.

    Here's a sample one - you can modify it to suit your needs, but it covers basic importing of text and character names:

    http://pasteall.org/1530893/csharp

    Place it in a script named "ImportSpeechEditor", and place it in an Editor asset folder. It takes a CSV file of three columns:

    1. "Is player?" - 0 for no, 1 for yes
    2. "Character name" - the name of a character in the scene
    3. "Line text" - the speech text itself

    Here's a sample file:
    http://pasteall.org/1530898

    To import it, add a new Cutscene to your scene and go to "Adventure Creator -> Import speech lines" in the top toolbar. Assign the Cutscene and select the CSV file. It should then replace the Cutscene's Actions with the imported data.

    Again, you can modify it to suit your own needs.

    Also worth mentioning is that AC has integration with Dialogue System, which can be used to import speech from professional speechwriting tools such articy:draft and ChatMapper.

  • Wow! That works great! I'll check out Dialogue System since I got it in a sale a while back and it looks like it also imports CSV, but the simple text to nodes may be all I need. Thank you!

  • Sorry for re-opening this old thread, but would you (or anyone else) be able to re-provide that example? It seems the link no longer works, but from the discussion here it seems like its exactly what I require.

  • edited March 2023

    Welcome to the community, @Nergal.

    You're in luck - I believe this was it:

    using UnityEngine;
    using UnityEditor;
    using System.Collections;
    using System.Collections.Generic;
    using AC;
    
    public class ImportSpeechEditor : EditorWindow
    {
    
        private Cutscene cutsceneToOverwrite;
    
    
        [MenuItem ("Adventure Creator/Addons/Import speech lines", false, 10)]
        public static void Init ()
        {
            // Get existing open window or if none, make a new one:
            ImportSpeechEditor window = (ImportSpeechEditor) EditorWindow.GetWindow (typeof (ImportSpeechEditor));
            window.titleContent.text = "Speech importer";
        }
    
    
        private void OnGUI ()
        {
            cutsceneToOverwrite = (Cutscene) EditorGUILayout.ObjectField ("Cutscene to overwrite:", cutsceneToOverwrite, typeof (Cutscene), true);
    
            if (GUILayout.Button ("Import from file"))
            {
                ImportFromFile ();
            }
        }
    
    
        private void ImportFromFile ()
        {
            string fileName = EditorUtility.OpenFilePanel ("Import inventory item data", "Assets", "csv");
            if (fileName.Length == 0)
            {
                return;
            }
    
            if (System.IO.File.Exists (fileName))
            {
                string csvText = Serializer.LoadFile (fileName);
                string[,] csvOutput = CSVReader.SplitCsvGrid (csvText);
    
                GenerateLines (csvOutput);
            }
        }
    
    
        private void GenerateLines (string[,] csvData)
        {
            int numCols = csvData.GetLength (0)-1;
    
            if (numCols < 3) return;
    
            int numRows = csvData.GetLength (1);
    
            List<ImportedSpeechLine> importedSpeechLines = new List<ImportedSpeechLine>();
    
            for (int row = 1; row < numRows; row ++)
            {
                if (csvData [0, row] != null && csvData [0, row].Length > 0)
                {
                    int isPlayerInt = 0;
                    if (int.TryParse (csvData [0, row], out isPlayerInt))
                    {
                        bool isPlayer = (isPlayerInt == 1);
                        string characterName = csvData [1, row];
                        string lineText = csvData [2, row];
    
                        importedSpeechLines.Add (new ImportedSpeechLine (isPlayer, characterName, lineText));
                    }
                }
            }
    
            ImportLines (importedSpeechLines.ToArray ());
        }
    
    
        private void ImportLines (ImportedSpeechLine[] importedSpeechLines)
        {
            if (cutsceneToOverwrite != null)
            {
                cutsceneToOverwrite.actions.Clear ();
    
                foreach (ImportedSpeechLine importedSpeechLine in importedSpeechLines)
                {
                    ActionSpeech speechAction = importedSpeechLine.GenerateAction ();
                    cutsceneToOverwrite.actions.Add (speechAction);
    
                }
    
                // Save
                UnityVersionHandler.CustomSetDirty (cutsceneToOverwrite, true);
            }
        }
    
    
        private struct ImportedSpeechLine
        {
    
            private string text;
            private bool isPlayer;
            private string speakerName;
    
    
            public ImportedSpeechLine (bool isPlayer, string speakerName, string text)
            {
                this.isPlayer = isPlayer;
                this.speakerName = speakerName;
                this.text = text;
            }
    
    
            public ActionSpeech GenerateAction ()
            {
                ActionSpeech speechAction = (ActionSpeech) ScriptableObject.CreateInstance (typeof (ActionSpeech));
    
                speechAction.messageText = text;
                speechAction.isPlayer = isPlayer;
    
                if (!isPlayer && !string.IsNullOrEmpty (speakerName))
                {
                    AC.Char[] allCharacters = GameObject.FindObjectsOfType <AC.Char>();
                    foreach (AC.Char character in allCharacters)
                    {
                        if (character.GetName () == speakerName)
                        {
                            speechAction.speaker = character;
                            break;
                        }
                    }
                }
    
                return speechAction;
            }
    
        }
    
    }
    
  • Thank you for the welcome and thank you for the example! It's very much appreciated :)

  • Oh, well, I was about to ask about something similar, but I see it's already there :P

    Maybe I wouldn't use it after all text has been imported, but since I've got plenty of ping-pong dialogues, it really gets boring, since our writer isn't very familiar with Unity and I had to do it by myself, with little time to build my own tools for that.

    I'd love to see it as a core sub-tool, since it really speeds up laying down at least the barebone of the conversation. It can later be decorated with camera changes and so on.

    Aligning each speaker's action/speech on a specific x distance from the root node (1 column per actor in the Actionlist editor) would help to maintain some order :)

  • I have been finding this feature and landed on this page. It seems very useful as my game is text heavy. But before diving in to modifying the code, or purchasing Dialog System, could you please tell me how it works with AC actionlists?

    Like, can Dialog System (DS) controls every AC action, so that I can build an entire actionlist in DS? If yes, how about custom actions?

    Or is that DS is only for triggering certain actions (like dialog & conversation), and I will have to play a whole action sequence by toggling between DS and AC controls?

    Thank you for your help.

  • edited April 2020

    I believe DS relies on custom Actions, but I'm not an official voice for it. You should contact its developer, Tony / PixelCrushers, for a definitive answer.

  • 'UnityVersionHandler' does not contain a definition for 'SetWindowTitle'

    This script doesnt work anymore.

  • Would also be nice to have an example because all those pasteall.org links dont work anymore

  • Replace:

    UnityVersionHandler.SetWindowTitle (window, "Speech importer");
    

    with:

    window.titleContent.text = "Speech importer";
    
  • Alright thanks. I get this error.

    "NullReferenceException: Object reference not set to an instance of an object
    ImportSpeechEditor.GenerateLines (System.String[,] csvData) (at Assets/Editor/ImportSpeechEditor.cs:53)
    ImportSpeechEditor.ImportFromFile () (at Assets/Editor/ImportSpeechEditor.cs:46)
    ImportSpeechEditor.OnGUI () (at Assets/Editor/ImportSpeechEditor.cs:28)
    UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition, UnityEngine.Rect viewRect) (at <50f55621a2ca4f31a35283e2979a8bf5>:0)
    UnityEditor.DockArea.DrawView (UnityEngine.Rect viewRect, UnityEngine.Rect dockAreaRect) (at <50f55621a2ca4f31a35283e2979a8bf5>:0)
    UnityEditor.DockArea.OldOnGUI () (at <50f55621a2ca4f31a35283e2979a8bf5>:0)
    UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <1cdf5c2cc10149169242b9590b7ebb6b>:0)
    UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, UnityEngine.Matrix4x4 worldTransform, UnityEngine.Rect clippingRect, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <1cdf5c2cc10149169242b9590b7e"

  • Is this how the csv is supposed to look?

  • edited April 2021

    It's how it looks as raw text that matters. The above should look like the following when opened up in a raw text editor:

    1,Aya,This is me just testing the whole thing.
    

    You can import this into a spreadsheet, but you'd need to make sure it doesn't apply any formatting.

  • Alright i got it working using an online csv maker. I think excel has a csv issue. Oh well it works now that's all that matters.

    Thanks.

  • In my experience, OpenOffice handles CSVs well.

  • Another apology for bumping this old thread, but I was trying to integrate this import speech script into AC and I ran into two error messages:

    Assets/Editor/ImportSpeechEditor.cs(315,1): error CS1519: Invalid token '<' in class, record, struct, or interface member declaration

    Assets/Editor/ImportSpeechEditor.cs(316,1): error CS1519: Invalid token '}' in class, record, struct, or interface member declaration

    I'm not entirely sure how to solve those scripting errors. I appreciate any support!

  • Welcome to the community, @bannonjacob.

    The errors you're getting suggest the script is over 300 lines, but the ImportSpeechEditor code above should only be 141. Are you modifying the code within?

  • Hi Chris! That's correct. I'm pasting the script from the wiki: https://adventure-creator.fandom.com/wiki/Generating_speech_from_spreadsheets

    I assume that the copy/paste job is adding space between the brackets and I should reduce the gaps?

  • @ChrisIceBox

    Instead of using the one from the wiki page, I used the above one you posted and it seems to have solved the issue. Much thanks! :)

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.