Search Unity

Dialogue System works in Editor but not in Build

Discussion in 'Scripting' started by Kanassa, May 9, 2021.

Thread Status:
Not open for further replies.
  1. Kanassa

    Kanassa

    Joined:
    Nov 1, 2018
    Posts:
    6
    For my current project, I patched together a basic dialogue system strung together by different tutorials and prayer. Dialogue is composed of going through the child node of a scriptable object in an array. And for the most part it seems to work. When I test it in the editor, everything seems to work as intended, the UI works fine, the text reflects which node it is on, it transitions to different nodes as it should, it's able to trigger scripts through attatched event actions and can be started and ended without error. This not including that when the conversation has no nodes left to go to, there will be a 'IndexOutOfRangeException' error.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. #if UNITY_EDITOR
    5. using UnityEditor;
    6. #endif
    7.  
    8. namespace GGM.Dialogue
    9. {
    10.     [CreateAssetMenu(fileName = "New Dialogue", menuName = "Dialogue", order = 0)]
    11.     public class Dialogue : ScriptableObject, ISerializationCallbackReceiver
    12.     {
    13.         [SerializeField]
    14.         List<DialogueNode> nodes = new List<DialogueNode>();
    15.         [SerializeField]
    16.         Vector2 newNodeOffset = new Vector2(250, 0);
    17.  
    18.         Dictionary<string, DialogueNode> nodeLookup = new Dictionary<string, DialogueNode>();
    19.  
    20.         private void OnValidate()
    21.         {
    22.             nodeLookup.Clear();
    23.             foreach(DialogueNode node in GetAllNodes())
    24.             {
    25.                 nodeLookup[node.name] = node;
    26.             }
    27.         }
    28.         public IEnumerable<DialogueNode> GetAllNodes()
    29.         {
    30.             return nodes;
    31.         }
    32.  
    33.         public DialogueNode GetRootNode()
    34.         {
    35.             return nodes[0];
    36.         }
    37.  
    38.         public IEnumerable<DialogueNode> GetAllChildren(DialogueNode parentNode)
    39.         {
    40.             List<DialogueNode> result = new List<DialogueNode>();
    41.             foreach (string childID in parentNode.GetChildren())
    42.             {
    43.                 if(nodeLookup.ContainsKey(childID))
    44.                 {
    45.                     yield return nodeLookup[childID];
    46.                 }              
    47.             }
    48.         }
    49.  
    50.         public IEnumerable<DialogueNode> GetPlayerChildren(DialogueNode currentNode)
    51.         {
    52.             foreach(DialogueNode node in GetAllChildren(currentNode))
    53.             {
    54.                 if(node.IsPlayerSpeaking())
    55.                 {
    56.                     yield return node;
    57.                 }
    58.             }
    59.         }
    60.  
    61.         public IEnumerable<DialogueNode> GetAIChildren(DialogueNode currentNode)
    62.         {
    63.             foreach (DialogueNode node in GetAllChildren(currentNode))
    64.             {
    65.                 if (!node.IsPlayerSpeaking())
    66.                 {
    67.                     yield return node;
    68.                 }
    69.             }
    70.  
    71.         }
    72.  
    73.         public void CreateNode(DialogueNode parent)
    74.         {
    75.             DialogueNode newNode = MakeNode(parent);
    76. #if UNITY_EDITOR
    77.             Undo.RegisterCreatedObjectUndo(newNode, "Created Dialogue Node");
    78.             Undo.RecordObject(this, "Added Dialogue Node");
    79.             AddNode(newNode);
    80. #endif
    81.         }
    82.  
    83.         public void DeleteNode(DialogueNode nodeToDelete)
    84.         {
    85. #if UNITY_EDITOR
    86.             Undo.RecordObject(this, "Deleted Dialogue Node");
    87.             nodes.Remove(nodeToDelete);          
    88.             OnValidate();
    89.             CleanDanglingChildren(nodeToDelete);
    90.             Undo.DestroyObjectImmediate(nodeToDelete);
    91. #endif
    92.         }
    93.  
    94.             private DialogueNode MakeNode(DialogueNode parent)
    95.         {
    96.             DialogueNode newNode = CreateInstance<DialogueNode>();
    97.             newNode.name = System.Guid.NewGuid().ToString();
    98.  
    99.             if (parent != null)
    100.             {
    101.                 parent.AddChild(newNode.name);
    102.                 newNode.SetPlayerSpeaking(!parent.IsPlayerSpeaking());
    103.                 newNode.SetPosition(parent.GetRect().position + newNodeOffset);
    104.             }
    105.  
    106.             return newNode;
    107.         }
    108.  
    109.         private void AddNode(DialogueNode newNode)
    110.         {
    111.             nodes.Add(newNode);
    112.             OnValidate();
    113.         }
    114.  
    115.         private void CleanDanglingChildren(DialogueNode nodeToDelete)
    116.         {
    117.             foreach (DialogueNode node in GetAllNodes())
    118.             {
    119.                 node.RemoveChild(nodeToDelete.name);
    120.             }
    121.         }
    122.  
    123.         public void OnBeforeSerialize()
    124.         {
    125. #if UNITY_EDITOR
    126.             if (nodes.Count == 0)
    127.             {
    128.                 DialogueNode newNode = MakeNode(null);
    129.                 AddNode(newNode);
    130.             }
    131.             if (AssetDatabase.GetAssetPath(this) != "")
    132.             {
    133.                 foreach(DialogueNode node in GetAllNodes())
    134.                 {
    135.                     if(AssetDatabase.GetAssetPath(node) == "")
    136.                     {
    137.                         AssetDatabase.AddObjectToAsset(node, this);
    138.                     }
    139.                 }
    140.             }
    141. #endif
    142.         }
    143.  
    144.         public void OnAfterDeserialize()
    145.         {
    146.  
    147.         }      
    148.     }
    149. }
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEditor;
    5. using UnityEditor.Callbacks;
    6. using UnityEngine;
    7.  
    8. namespace GGM.Dialogue.Editor
    9. {
    10.     public class DialogueEditor : EditorWindow
    11.     {
    12.         Dialogue selectedDialogue = null;
    13.         [NonSerialized]
    14.         GUIStyle nodeStyle;
    15.         [NonSerialized]
    16.         GUIStyle playerNodeStyle;
    17.         [NonSerialized]
    18.         DialogueNode draggingNode = null;
    19.         [NonSerialized]
    20.         Vector2 draggingOffset;
    21.         [NonSerialized]
    22.         DialogueNode creatingNode = null;
    23.         [NonSerialized]
    24.         DialogueNode deletingNode = null;
    25.         [NonSerialized]
    26.         DialogueNode linkingParentNode = null;
    27.         Vector2 scrollPosition;
    28.         [NonSerialized]
    29.         bool draggingCanvas = false;
    30.         [NonSerialized]
    31.         Vector2 draggingCanvasOffset;
    32.  
    33.         const float canvasSize = 4000;
    34.         const float backgroundSize = 50;
    35.  
    36.         [MenuItem("Window/Dialogue Editor")]
    37.         public static void ShowEditorWindow()
    38.         {
    39.             GetWindow(typeof(DialogueEditor), false, "Dialogue Editor");
    40.         }
    41.  
    42.         [OnOpenAssetAttribute(1)]
    43.         public static bool OnOpenAsset(int instanceID, int line)
    44.         {
    45.             Dialogue dialogue = EditorUtility.InstanceIDToObject(instanceID) as Dialogue;
    46.             if(dialogue != null)
    47.             {
    48.                 ShowEditorWindow();
    49.                 return true;
    50.             }          
    51.             return false;
    52.         }
    53.  
    54.         private void OnEnable()
    55.         {
    56.             Selection.selectionChanged += OnSelectionChanged;
    57.  
    58.             nodeStyle = new GUIStyle();
    59.             nodeStyle.normal.background = EditorGUIUtility.Load("node1") as Texture2D;
    60.             nodeStyle.normal.textColor = Color.white;
    61.             nodeStyle.padding = new RectOffset(20, 20, 20, 20);
    62.             nodeStyle.border = new RectOffset(12, 12, 12, 12);
    63.  
    64.             playerNodeStyle = new GUIStyle();
    65.             playerNodeStyle.normal.background = EditorGUIUtility.Load("node2") as Texture2D;
    66.             playerNodeStyle.normal.textColor = Color.white;
    67.             playerNodeStyle.padding = new RectOffset(20, 20, 20, 20);
    68.             playerNodeStyle.border = new RectOffset(12, 12, 12, 12);
    69.         }
    70.  
    71.         private void OnSelectionChanged()
    72.         {
    73.             Dialogue newDialogue = Selection.activeObject as Dialogue;
    74.                 if(newDialogue != null)
    75.             {
    76.                 selectedDialogue = newDialogue;
    77.                 Repaint();
    78.             }
    79.         }
    80.  
    81.         private void OnGUI()
    82.         {
    83.             if(selectedDialogue == null)
    84.             {
    85.                 EditorGUILayout.LabelField("No Dialogue Selected.");
    86.             }
    87.             else
    88.             {
    89.                 ProcessEvents();
    90.                 scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
    91.  
    92.                 Rect canvas = GUILayoutUtility.GetRect(canvasSize, canvasSize);
    93.                 Texture2D backgroundtex = Resources.Load("background") as Texture2D;
    94.                 Rect textCoords = new Rect(0, 0, canvasSize / backgroundSize, canvasSize / backgroundSize);
    95.                 GUI.DrawTextureWithTexCoords(canvas, backgroundtex, textCoords);
    96.  
    97.                 foreach (DialogueNode node in selectedDialogue.GetAllNodes())
    98.                 {
    99.                     DrawConnections(node);
    100.                 }
    101.                 foreach (DialogueNode node in selectedDialogue.GetAllNodes())
    102.                 {
    103.                     DrawNode(node);
    104.                 }
    105.  
    106.                 EditorGUILayout.EndScrollView();
    107.  
    108.                 if (creatingNode != null)
    109.                 {                  
    110.                     selectedDialogue.CreateNode(creatingNode);
    111.                     creatingNode = null;
    112.                 }
    113.                 if(deletingNode != null)
    114.                 {
    115.                     selectedDialogue.DeleteNode(deletingNode);
    116.                     deletingNode = null;
    117.                 }
    118.             }
    119.         }
    120.  
    121.         private void ProcessEvents()
    122.         {
    123.             if(Event.current.type == EventType.MouseDown && draggingNode == null)
    124.             {
    125.                 draggingNode = GetNodeAtPoint(Event.current.mousePosition + scrollPosition);
    126.                 if(draggingNode != null)
    127.                 {
    128.                     draggingOffset = draggingNode.GetRect().position - Event.current.mousePosition;
    129.                     Selection.activeObject = draggingNode;
    130.                 }
    131.                 else
    132.                 {
    133.                     draggingCanvas = true;
    134.                     draggingCanvasOffset = Event.current.mousePosition + scrollPosition;
    135.                     Selection.activeObject = selectedDialogue;
    136.                 }
    137.             }
    138.             else if(Event.current.type == EventType.MouseDrag && draggingNode != null)
    139.             {
    140.                 draggingNode.SetPosition(Event.current.mousePosition + draggingOffset);
    141.                
    142.                 //Update scrollPosition
    143.                 GUI.changed = true;
    144.             }
    145.             else if (Event.current.type == EventType.MouseDrag && draggingCanvas)
    146.             {
    147.                 scrollPosition = draggingCanvasOffset - Event.current.mousePosition;
    148.  
    149.                 GUI.changed = true;
    150.             }
    151.             else if(Event.current.type == EventType.MouseUp && draggingNode != null)
    152.             {
    153.                 draggingNode = null;
    154.             }
    155.             else if (Event.current.type == EventType.MouseUp && draggingCanvas)
    156.             {
    157.                 draggingCanvas = false;
    158.             }
    159.         }
    160.        
    161.  
    162.         private void DrawNode(DialogueNode node)
    163.         {
    164.             GUIStyle style = nodeStyle;
    165.             if(node.IsPlayerSpeaking())
    166.             {
    167.                 style = playerNodeStyle;
    168.             }
    169.  
    170.             GUILayout.BeginArea(node.GetRect(), style);
    171.  
    172.             node.SetText(EditorGUILayout.TextField(node.GetText()));
    173.  
    174.             GUILayout.BeginHorizontal();
    175.             if(GUILayout.Button("Add Node"))
    176.             {
    177.                 creatingNode = node;              
    178.             }
    179.             if (GUILayout.Button("Delete Node"))
    180.             {
    181.                 deletingNode = node;
    182.             }
    183.             GUILayout.EndHorizontal();
    184.  
    185.             DrawLinkButtons(node);
    186.  
    187.             GUILayout.EndArea();
    188.         }
    189.  
    190.         private void DrawConnections(DialogueNode node)
    191.         {
    192.             Vector3 startPosition = new Vector2(node.GetRect().xMax, node.GetRect().center.y);          
    193.             foreach (DialogueNode childNode in selectedDialogue.GetAllChildren(node))
    194.             {              
    195.                 Vector3 endPosition = new Vector2(childNode.GetRect().xMin, childNode.GetRect().center.y);
    196.                 Vector3 controlPointOffset = endPosition - startPosition;
    197.                 controlPointOffset.y = 0;
    198.                 controlPointOffset.x *= 0.8f;
    199.                 Handles.DrawBezier(startPosition, endPosition,
    200.                     startPosition + controlPointOffset,
    201.                     endPosition - controlPointOffset,
    202.                     Color.white, null, 4f);
    203.             }
    204.         }
    205.  
    206.         private DialogueNode GetNodeAtPoint(Vector2 point)
    207.         {
    208.             DialogueNode foundNode = null;
    209.             foreach(DialogueNode node in selectedDialogue.GetAllNodes())
    210.             {
    211.                 if(node.GetRect().Contains(point))
    212.                 {
    213.                     foundNode = node;
    214.                 }
    215.             }
    216.  
    217.             return foundNode;
    218.         }
    219.  
    220.         private void DrawLinkButtons(DialogueNode node)
    221.         {
    222.             if (linkingParentNode == null)
    223.             {
    224.                 if (GUILayout.Button("Link Node"))
    225.                 {
    226.                     linkingParentNode = node;
    227.                 }
    228.             }
    229.             else if(linkingParentNode == node)
    230.             {
    231.                 if (GUILayout.Button("Cancle"))
    232.                 {
    233.                     linkingParentNode = null;
    234.                 }
    235.             }
    236.             else if(linkingParentNode.GetChildren().Contains(node.name))
    237.             {
    238.                 if (GUILayout.Button("Unlink"))
    239.                 {
    240.                     linkingParentNode.RemoveChild(node.name);
    241.                     linkingParentNode = null;
    242.                 }
    243.             }
    244.             else
    245.             {
    246.                 if (GUILayout.Button("Child Node"))
    247.                 {
    248.                     linkingParentNode.AddChild(node.name);
    249.                     linkingParentNode = null;
    250.                 }
    251.             }
    252.         }
    253.     }  
    254. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using UnityEngine;
    5. using UnityEditor;
    6.  
    7. namespace GGM.Dialogue.Editor
    8. {
    9.     public class DialogueModificationProcessor : UnityEditor.AssetModificationProcessor
    10.     {
    11.         private static AssetMoveResult OnWillMoveAsset(string sourcePath, string destinationPath)
    12.         {
    13.             Dialogue dialogue = AssetDatabase.LoadMainAssetAtPath(sourcePath) as Dialogue;
    14.             if(dialogue == null)
    15.             {
    16.                 return AssetMoveResult.DidNotMove;
    17.             }
    18.  
    19.             if(Path.GetDirectoryName(sourcePath) != Path.GetDirectoryName(destinationPath))
    20.             {
    21.                 return AssetMoveResult.DidNotMove;
    22.             }
    23.  
    24.             dialogue.name = Path.GetFileNameWithoutExtension(destinationPath);
    25.  
    26.             return AssetMoveResult.DidNotMove;
    27.         }
    28.     }
    29. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. #if UNITY_EDITOR
    5. using UnityEditor;
    6. #endif
    7.  
    8. namespace GGM.Dialogue
    9. {
    10.     public class DialogueNode : ScriptableObject
    11.     {
    12.         [SerializeField]
    13.         bool isPlayerSpeaking = false;
    14.         [SerializeField]
    15.         string text;
    16.         [SerializeField]
    17.         List<string> children = new List<string>();
    18.         [SerializeField]
    19.         Rect rect = new Rect(0, 0, 200, 100);
    20.         [SerializeField]
    21.         string onEnterAction;
    22.         [SerializeField]
    23.         string onExitAction;
    24.  
    25.         public Rect GetRect()
    26.         {
    27.             return rect;
    28.         }
    29.  
    30.         public string GetText()
    31.         {
    32.             return text;
    33.         }
    34.  
    35.         public bool IsPlayerSpeaking()
    36.         {
    37.             return isPlayerSpeaking;
    38.         }
    39.  
    40.         public string GetOnEnterAction()
    41.         {
    42.             return onEnterAction;
    43.         }
    44.  
    45.         public string GetOnExitAction()
    46.         {
    47.             return onExitAction;
    48.         }
    49.  
    50.  
    51.         public void SetPlayerSpeaking(bool newIsPlayerSpeaking)
    52.         {
    53. #if UNITY_EDITOR
    54.             Undo.RecordObject(this, "Set Player Speaking");
    55.             isPlayerSpeaking = newIsPlayerSpeaking;
    56.             EditorUtility.SetDirty(this);
    57. #endif
    58.         }
    59.  
    60.         public void SetPosition(Vector2 newPosition)
    61.         {
    62. #if UNITY_EDITOR
    63.             Undo.RecordObject(this, "Move Dialogue Node");
    64.             rect.position = newPosition;
    65.             EditorUtility.SetDirty(this);
    66. #endif
    67.         }
    68.  
    69.         public void SetText(string newText)
    70.         {
    71.             if (newText != text)
    72.             {
    73. #if UNITY_EDITOR
    74.                 Undo.RecordObject(this, "Update Dialogue Text");
    75.                 text = newText;
    76.                 EditorUtility.SetDirty(this);
    77. #endif
    78.             }
    79.         }
    80.  
    81.         public List<string> GetChildren()
    82.         {
    83.             return children;
    84.         }
    85.  
    86.  
    87.         public void AddChild(string childID)
    88.         {
    89. #if UNITY_EDITOR
    90.             Undo.RecordObject(this, "Add Dialogue Link");
    91.             children.Add(childID);
    92.             EditorUtility.SetDirty(this);
    93. #endif
    94.         }
    95.  
    96.         public void RemoveChild(string childID)
    97.         {
    98. #if UNITY_EDITOR
    99.             Undo.RecordObject(this, "Break Dialogue Link");
    100.             children.Remove(childID);
    101.             EditorUtility.SetDirty(this);
    102. #endif
    103.         }
    104.     }
    105. }
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using UnityEngine;
    6. using UnityEngine.UI;
    7.  
    8. namespace GGM.Dialogue
    9. {
    10.     public class PlayerConversant : MonoBehaviour
    11.     {
    12.         Dialogue currentDialogue;
    13.         DialogueNode currentNode = null;
    14.         AIConversant currentConversant = null;
    15.         bool isChoosing = false;
    16.  
    17.         public ScrollRect myScrollRect;
    18.  
    19.         public event Action onConversationUpdated;
    20.  
    21.         public void StartDialouge(AIConversant newConversant, Dialogue newDialogue)
    22.         {
    23.             currentConversant = newConversant;
    24.             currentDialogue = newDialogue;
    25.             currentNode = currentDialogue.GetRootNode();
    26.             TriggerEnterAction();
    27.             onConversationUpdated();
    28.         }
    29.  
    30.         public void Quit()
    31.         {          
    32.             currentDialogue = null;
    33.             TriggerExitAction();
    34.             currentNode = null;
    35.             isChoosing = false;
    36.             currentConversant = null;
    37.             onConversationUpdated();
    38.         }
    39.  
    40.         public bool IsActive()
    41.         {
    42.             return currentDialogue != null;
    43.         }
    44.  
    45.         public bool IsChoosing()
    46.         {
    47.             return isChoosing;
    48.         }
    49.  
    50.         public string GetText()
    51.         {
    52.             if(currentNode == null)
    53.             {
    54.                 return "";
    55.             }
    56.  
    57.             return currentNode.GetText();
    58.         }
    59.  
    60.         public IEnumerable<DialogueNode> GetChoices()
    61.         {
    62.             return currentDialogue.GetPlayerChildren(currentNode);
    63.         }
    64.  
    65.         public void SelectChoice(DialogueNode chosenNode)
    66.         {
    67.             currentNode = chosenNode;
    68.             TriggerEnterAction();
    69.             isChoosing = false;
    70.             Next();
    71.         }
    72.  
    73.         public void Next()
    74.         {
    75.             int numPlayerResponses = currentDialogue.GetPlayerChildren(currentNode).Count();
    76.             myScrollRect.verticalNormalizedPosition = 0f;
    77.             if (numPlayerResponses > 0)
    78.             {
    79.                 isChoosing = true;
    80.                 TriggerExitAction();
    81.                 onConversationUpdated();
    82.                 return;
    83.             }
    84.             DialogueNode[] children = currentDialogue.GetAIChildren(currentNode).ToArray();
    85.             Debug.Log("Array size = "+ children.Length);
    86.             TriggerExitAction();
    87.             currentNode = children[0];
    88.             TriggerEnterAction();
    89.             onConversationUpdated();
    90.         }
    91.  
    92.         public bool HasNext()
    93.         {
    94.             return currentDialogue.GetAllChildren(currentNode).Count() > 0;
    95.         }
    96.  
    97.         private void TriggerEnterAction()
    98.         {
    99.             if(currentNode != null)
    100.             {
    101.                 TriggerAction(currentNode.GetOnEnterAction());
    102.             }
    103.         }
    104.  
    105.         private void TriggerExitAction()
    106.         {
    107.             if (currentNode != null)
    108.             {
    109.                 TriggerAction(currentNode.GetOnExitAction());
    110.             }
    111.         }
    112.  
    113.         private void TriggerAction(string action)
    114.         {
    115.             if (action == "") return;
    116.  
    117.             foreach(DialogueTrigger trigger in currentConversant.GetComponents<DialogueTrigger>())
    118.             {
    119.                 trigger.Trigger(action);
    120.             }
    121.         }
    122.     }
    123. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. namespace GGM.Dialogue
    7. {
    8.     public class AIConversant : MonoBehaviour
    9.     {
    10.         [SerializeField] Dialogue dialogue = null;
    11.         public GameObject Player;
    12.         public GameObject ActionDisplay;
    13.         public GameObject Cam;
    14.         public GameObject DialogueCam;
    15.         public PlayerLook playerLook;
    16.         public GameObject DialougeUI;
    17.         public GameObject NonDialougeUI;
    18.  
    19.         public Transform diaCam;
    20.         public Transform lookTarget;
    21.         public Transform playerLocate;
    22.  
    23.         public Vector3 origPos;
    24.  
    25.         public bool inPos;
    26.         public bool isTalking;
    27.         public bool triggerByTouch;
    28.         public bool notActive;
    29.  
    30.         public float TheDistance;
    31.         public float playerLookDistance;
    32.         public float Range;
    33.  
    34.         void OnTriggerEnter()
    35.         {
    36.             inPos = true;          
    37.         }
    38.  
    39.         void OnTriggerExit()
    40.         {
    41.             inPos = false;
    42.         }
    43.  
    44.         void Start()
    45.         {
    46.             Player = GameObject.Find("Player/Player 1");          
    47.             ActionDisplay = GameObject.Find("Player/Canvas/Action Text");
    48.             Cam = GameObject.Find("Player/Player 1/CameraNight");
    49.             playerLook = Cam.GetComponent<PlayerLook>() as PlayerLook;
    50.             DialogueCam = GameObject.Find("Player/DialogueCam");
    51.             origPos = DialogueCam.gameObject.transform.position;          
    52.             DialougeUI = GameObject.Find("Player/Canvas/DialougeUI");
    53.             NonDialougeUI = GameObject.Find("Player/Canvas/StatUI");
    54.         }
    55.  
    56.         void OnMouseOver()
    57.         {
    58.             if(TheDistance <= Range && !notActive)
    59.             {
    60.                 if (!isTalking && !triggerByTouch)
    61.                 {
    62.                     ActionDisplay.SetActive(true);
    63.                 }
    64.             }          
    65.         }
    66.  
    67.         void OnMouseExit()
    68.         {
    69.             ActionDisplay.SetActive(false);
    70.         }
    71.  
    72.         void Update()
    73.         {
    74.             TheDistance = Vector3.Distance(this.gameObject.transform.position, Player.gameObject.transform.position);
    75.             playerLookDistance = playerLook.ToTarget;
    76.  
    77.             if(!notActive)
    78.             {
    79.                 if (TheDistance <= Range && !triggerByTouch)
    80.                 {
    81.                     ActionDisplay.SetActive(true);
    82.                 }
    83.  
    84.                 if (isTalking)
    85.                 {
    86.                     ActionDisplay.SetActive(false);
    87.                 }
    88.  
    89.                 if (TheDistance <= Range && !triggerByTouch)
    90.                 {
    91.                     if (Input.GetKeyDown("e"))
    92.                     {
    93.                         TriggerConvo();
    94.                     }
    95.                 }
    96.  
    97.                 if(!isTalking)
    98.                 {
    99.                     if (TheDistance <= Range && triggerByTouch)
    100.                     {
    101.                         TriggerConvo();
    102.                     }
    103.                 }              
    104.             }          
    105.         }
    106.  
    107.         public void TriggerConvo()
    108.         {
    109.             isTalking = true;
    110.             Player.GetComponent<PlayerMovement>().enabled = false;
    111.             Cam.GetComponent<Camera>().enabled = false;
    112.             Cam.GetComponent<PlayerLook>().enabled = false;
    113.             DialogueCam.GetComponent<Camera>().enabled = true;
    114.             Player.gameObject.transform.position = playerLocate.position;
    115.             DialougeUI.SetActive(true);
    116.             NonDialougeUI.SetActive(false);
    117.             DialogueCam.gameObject.transform.position = diaCam.position;
    118.             Player.gameObject.transform.LookAt(lookTarget.position);
    119.             DialogueCam.gameObject.transform.LookAt(lookTarget.position);
    120.             if(dialogue == null)
    121.             {
    122.                 //Debug.Log("Dialogue is not null");
    123.             }
    124.  
    125.             else
    126.             {
    127.                 //Debug.Log("Dialogue is null");
    128.             }
    129.            
    130.             Player.GetComponent<PlayerConversant>().StartDialouge(this, dialogue);
    131.             Cursor.lockState = CursorLockMode.Confined;
    132.         }
    133.  
    134.         public void Reset()
    135.         {
    136.             DialogueCam.GetComponent<Camera>().enabled = false;
    137.             Player.GetComponent<PlayerMovement>().enabled = true;
    138.             Cam.GetComponent<Camera>().enabled = true;
    139.             Cam.GetComponent<PlayerLook>().enabled = true;
    140.             DialogueCam.gameObject.transform.position = origPos;
    141.             DialougeUI.SetActive(false);
    142.             NonDialougeUI.SetActive(true);
    143.             isTalking = false;
    144.             Player.GetComponent<PlayerConversant>().Quit();
    145.             Cursor.lockState = CursorLockMode.Locked;
    146.         }
    147.  
    148.         public void autoExit()
    149.         {
    150.             StartCoroutine(autoExitSequence());
    151.         }
    152.  
    153.         private IEnumerator autoExitSequence()
    154.         {
    155.             yield return new WaitForSeconds(5);
    156.             Reset();
    157.             DeleteConvo();
    158.         }
    159.  
    160.         public void DeleteConvo()
    161.         {
    162.             notActive = true;
    163.         }
    164.     }
    165. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Events;
    5.  
    6. namespace GGM.Dialogue
    7. {
    8.     public class DialogueTrigger : MonoBehaviour
    9.     {
    10.         [SerializeField] string action;
    11.         [SerializeField] UnityEvent onTrigger;
    12.  
    13.         public void Trigger(string actionToTrigger)
    14.         {
    15.             if(actionToTrigger == action)
    16.             {
    17.                 onTrigger.Invoke();
    18.             }
    19.         }
    20.     }
    21. }

    So, build the game, open it up and try the conversation system. UI comes on, dialogue reflects the first node and... The conversation can't continue. The game doesn't freeze or anything, but the dialogue system doesn't bring in the next node with all the player responses. At first, I thought maybe something in the game was stopping the script from manually triggering the 'next' function, so I added in an 'auto next' script to the conversation trigger and rebuilt; the problem still persisted.

    I looked in the Player Log:

    Which seems to suggest that the problem isn't that the Next function isn't being triggered, but that the game has nothing to proceed to. I have been at this for two weeks and I cannot figure out what's being lost in the build that's causing this, the assets that trigger and assign conversation come directly from the asset folder so it's not some sort of prefab or scene-specific problem and the same error comes when I try and use other conversations too.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,738
    How do they "come directly from?" If you're using any methods in System.IO it will NEVER work in the build. Unity destroys your project file hierarchy and grinds your assets into a silky-fine powdery paste before putting them into the final build, so you MUST use scene references or use Resources.Load() methods.

    Also, here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

    http://plbm.com/?p=236

    To track it down, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run?
    - what are the values of the variables involved? Are they initialized?

    Knowing this information will help you reason about the behavior you are seeing.

    You could also just display various important quantities in UI Text elements to watch them change as you playtest.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494
     
  3. Kanassa

    Kanassa

    Joined:
    Nov 1, 2018
    Posts:
    6
    I mean as in the Dialogue Object that conversation system accesses is dragged and dropped from the assets rather than a GameObject already in the scene.


    Anyway, your advice about more debugging comments managed to lead me to an answer, I'd been so focused on putting debug logs around the Next() function being triggered that I didn't think to trace the node's data back. Long story short, the problem was the OnValidate() function, which clears the current node so that it can be replaced with the next one in the Next() function, can't be triggered as usual in the build, so I added an Awake() function that triggers it upon starting the game and everything seems to work fine.

    Thank you very much!
     
  4. mjkjx34

    mjkjx34

    Joined:
    Sep 19, 2021
    Posts:
    3
    Thanks...years later and this still works!
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    Please use the Like button to show appreciation rather than necroing the thread for everyone.

    Thanks.
     
Thread Status:
Not open for further replies.