So I’m working on a game and I decided to create a scriptable object class to store the data for different conversations. Here’s the class:
[Serializable]
[CreateAssetMenu (fileName = "ConversationData", menuName = "ScriptableObjects/ConversationData")]
public class ConversationData : ScriptableObject
{
public string NpcName;
public string[] Interlocutors;
public bool Loop;
public List<List<Tuple<int, string>>> Conversations;
}
And since Unity doesn’t have a way (at least that I’m aware of) to show a list of lists of tuples in the inspector without making use of a custom inspector, that’s exactly what I did:
[ExecuteAlways]
[CustomEditor (typeof (ConversationData))]
public class DialogueGUI : Editor
{
private bool _dialoguesFoldout;
private int _dialogues, _lines, _interlocutorIndex;
private string _text;
private List<List<Tuple<int, string>>> _conversations;
private List<Tuple<int, string>> _conversation;
private ConversationData _conversationData;
public int Dialogues
{
set
{
_dialogues = value < 0 ? 0 : value;
}
}
public int Lines
{
set => _lines = value < 0 ? 0 : value;
}
public int InterlocutorIndex
{
set
{
_interlocutorIndex = Mathf.Clamp (value, 0, _conversationData.Interlocutors.Length);
}
}
// .
private void OnEnable ()
{
_conversationData = (ConversationData) this.target;
_dialoguesFoldout = true;
}
// .
public override void OnInspectorGUI ()
{
base.OnInspectorGUI ();
_dialoguesFoldout = EditorGUILayout.Foldout (_dialoguesFoldout, "Dialogues");
if (_dialoguesFoldout == true)
{
_conversations = _conversationData.Conversations != null ? _conversationData.Conversations : new List<List<Tuple<int, string>>> ();
EditorGUI.indentLevel += 1;
Dialogues = EditorGUILayout.IntField ("Conversations", _conversations.Count);
if (_conversations.Count != _dialogues)
{
if (_conversations.Count > _dialogues)
{
while (_conversations.Count != _dialogues)
{
_conversations.RemoveAt (_conversations.Count - 1);
}
}
else
{
while (_conversations.Count != _dialogues)
{
_conversations.Add (new List<Tuple<int, string>> ()); ;
}
}
}
for (int i = 0; i < _dialogues; i += 1)
{
EditorGUILayout.LabelField ("CONVERSATION " + i);
_conversation = _conversations <em>!= null ? _conversations *: new List<Tuple<int, string>> ();*</em>
EditorGUI.indentLevel += 1;
Lines = EditorGUILayout.IntField (“Lines”, _conversation.Count);
if (_conversation.Count != _lines)
{
if (_conversation.Count > _lines)
{
while (_conversation.Count != _lines)
{
_conversation.RemoveAt (_conversation.Count - 1);
}
}
else
{
while (_conversation.Count != _lines)
{
_conversation.Add (new Tuple<int, string> (0, “”));
}
}
}
for (int j = 0; j < _lines; j += 1)
{
EditorGUILayout.LabelField ("LINE " + j);
InterlocutorIndex = EditorGUILayout.IntField (“Interlocutor index”, _conversation[j].Item1);
EditorGUILayout.LabelField (“Text”);
_text = EditorGUILayout.TextArea (_conversation[j].Item2, new GUILayoutOption[] { GUILayout.Height (45) });
conversations*[j] = new Tuple<int, string> (interlocutorIndex, text);*
}
EditorGUI.indentLevel -= 1;
}_
_conversationData.Conversations = _conversations;
if (GUI.changed == true)
{
EditorUtility.SetDirty (_conversationData);
EditorSceneManager.MarkSceneDirty (SceneManager.GetActiveScene ());
}
this.serializedObject.ApplyModifiedProperties ();
}
}
}
This seems to work fine when it comes to edit and store the different values of the list I’ve previously mentioned. However, I quickly found out that the data of that list dissapeared when closing and reopening the project for some reason (yes, only the info contained on the list, not the rest of variables that make up the class). After looking for some info on different forums, I learned of the existence of functions like “SetDirty” or “ApplyModifiedProperties” (which, as you can see, I’m using inside the “OnInspectorGUI” method after modifying the scriptable object) that are supposedly meant to fix these issues, but I haven’t been able to solve the problem this way. I don’t know if I’m using them wrong, if there’s some stupid detail I’m missing that’s provoking all of this or it’s some kind of Unity bug. Whathever this might be, I’d appreciate the help a lot, I’ve been stuck on this for a few days now and it’s becoming kind of frustrating…
Oh, by the way, the version of Unity that I’m using is 2020.1.15f1.