- Home /
The question is answered, right answer was accepted
Is there a way to optimize working with arrays?
So im working on a nice and detailed dialogue system with many properties like an extensive control over the speeds and when to continue etc........im working using scriptable objects that work as dialogue and have an array of a class DialogueLine in it which contain multiple properties about the line for example who is speaking and stuff like that......however since my game is supposed to be very long, working with arrays in such an environment can be daunting.....also while you can add elements to the end of an array, you cannot do it in midst of two.....which is important since sometimes you just might need to edit the script a bit without screwing anything over.....this is how it looks right now...
i thought maybe i could edit the asset file of the scriptable object to do it and while it can help me add elements in any order i want....it's by no way a clean and efficient thing to work with......
Is there any method i can combine the benefits of both...i would prefer working in a text editor...there is a tool called yarnspinner....but i have no idea if it would work in my case and help me build scriptable objects......please help!
Thanks in advance
@Devster2020 sorry for disturbing ya again but if you have any advice ill be grateful
Answer by Devster2020 · Jul 13, 2021 at 04:10 PM
Hello dear @rage_co I'm here
So, let's start from the beginning.. Using scriptable objects in your specific case would be very convenient, but as you have already said, it would lead you to a very long and difficult to manage list, as well as heavy in memory.
A possible solution would be to "break up" the entire dialogue into small dialogues to be loaded in runtime.. possible solution, but not as efficient as possible.
Method 1:
In my opinion, the best solution for you, who want to use a text editor, is to use a CSV file or similar stuff and then load it into memory when you need it.. even this however, it would be convenient to divide it into various sub-dialogs.
Here a preview of a CSV file (viewed on Apple Numbers App):
Method 2:
The last idea that comes to mind in a few minutes, is to make a .txt file formatted according to your needs, writing a line for each value and inserting a break line when moving on to the next element. Here is an example of a formatted file:
Conclusions:
The methods listed above may not be suitable for your use .. actually, I don't really know how you set everything up and if in the "listeners" item you need to link a prefab, a gameObject or other, which would require further modifications or tricks to to adapt.
I hope you can find the best solution to your problem and that one of mine will help you.
Im already using dialogues as sub objects to objects called scenes which allow me to properly format multiple dialogue objects and save a lot of headache....the problem is, sometimes these dialogues tend to be really long and exhausting to work with.... I like the txt file idea, but i don't know to implement it.....also the listener class is just one with one bool and two floats...so it's not much to worry about.....once again you have been a great resource, so if you have any hints about anyone or any internet resource that can guide me on how i can implement that text file idea, I think my problem would be completely solved.....if there isn't I'll continue my research and might even persist with the current method if it doesn't become too much pain
Thanks for the kind words you have dedicated to me.
The method is simple. Just read the text of the file and insert it in a string variable, after which divide the string into various pieces (each for each element) and, for each of them, read the values .. I am attaching a possible piece of code (forgive me if the compiler gives you errors .. i'm writing using a text editor, not an IDE):
private void ReadAndLoadDialogueFile(string filePath){
if(!File.Exists(filePath)){
Debug.LogError("File not exists!");
return;
}
string fileText = File.ReadAllText(filePath);
this.LoadDialogueInfos(fileText);
}
private void LoadDialogueInfos(string textOfFile){
string[] elements = textOfFile.Split("-----------------"); // This means that search into the text and split it when encounter this string;
List<Dialogue> dialogues = new List<Dialogue>();
foreach(string element in elements){
string[] values = element.Split("\n"); // Split the text for each ENTER encountered
int charactercode = Int32.Parse(values[0]);
string line = values[1];
int moodcode = values[2];
...... ect ....
Dialogue dialogue = new Dialogue();
dialogue.Charactercode = charactercode;
dialogue.Line = line;
...... ect ....
dialogues.Add(dialogue);
}
}
PS: if the code works, remember to remove the first line that I wrote in the example ("Dialogue 1:") because it will cause problems when you split the first text.
well actually characters in this system too are scriptable objects that contain all the information about that character...but as of now they have to be spoonfed to every dialogue object which can get scary in the long run.....i want to create a list or array of these characters and similary scene objects(not normal scenes but these are actually bundles of dialogue objects that make a scene inside the game, i should have picked the name more carefully).....which i can then just supply an index or code to the script to automatically take out the desired object from that array and put it in my game......
Answer by Bunny83 · Jul 14, 2021 at 12:34 AM
I'm not sure if you are aware of Unity's array editing features. First of all you can select an array element in the inspector and press CTRL+D to duplicate the selected element. So you effectively insert a value at that place. Furthermore for quite some time now Unity uses the ReorderableList to show arrays in the inspector. Notice the two small horizontal bars in front or each element. You can grab the element there and drag it around to reorder the elements.
I was quite sure that in the past Unity had also a shortcut to remove an array element. However none of the obvious keyboard shortcuts work. However you can use the context menu when clickin on an element and choose "delete array element".
Note that the usability could probably be greatly improved with a property drawer. Proper tooling is part of game development. Some people prefer to use just the stock functionality. However the Untiy editor is quite easy to extend, so you may want to have a look at editor scripting.
If you want to load the conversation data from an external file, I would highly recommend to use a more common format like json. This would be much more robust and flexible compared to a CSV file. JSON can actually represent arbitrary nested data.
Just as an example, over here I posted an example for a custom json mesh format and the corresponding loader. Yes, the loader code is really that short thanks to my SimpleJSON parser and the Unity extension file.
Nice ill look into that....devster2020 already gave me a solution which is quite similar but thanks anyway...i might need this....im very grateful
Answer by rage_co · Jul 15, 2021 at 12:31 PM
What just happened? whoever heard of a billion dollar using an external hosting service forgetting to renew their license insert laughing....Anyways @Devster2020 your code is working totally fine......except that .Split() takes a char value....so i used Char.Parse() and it worked but now i can only keep one character as a divider....which is undesirable since i use characters for formatting my text so i don't want to waste any of them......also....i want to be abled to automatically create and Save the scriptable object files.....here is what i made with your help
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class DialogueReader : MonoBehaviour
{
public char divider;
public DialoguesToImport[] toimport;
void Start()
{
foreach(DialoguesToImport import in toimport)
{
ReadDialogueFile(import.filepath, import.dialogue);
}
}
void ReadDialogueFile(string path, Dialogue dialogue)
{
if(!File.Exists(path))
{
Debug.LogError("no such file exists");
return;
}
string filedata = File.ReadAllText(path);
LoadDialogueData(filedata, dialogue);
}
void LoadDialogueData(string data, Dialogue dialogue)
{
string[] elements = data.Split(divider);
List<DialogueLine> dialogues = new List<DialogueLine>();
foreach(string element in elements)
{
string[] separator = {""};
string[] values = element.Split(',');
Debug.Log(values[0]);
int charactercode = Int32.Parse(values[0]);
string line = values[1];
int moodcode = Int32.Parse(values[2]);
bool enabled = false;
int listenercode = 0;
int listenermood = 0;
if(values.Length > 3)
{
enabled = true;
listenercode = Int32.Parse(values[3]);
if(values.Length >= 4)
{
listenermood = Int32.Parse(values[3]);
}
}
else
{
enabled = false;
listenercode = 0;
listenermood = 0;
}
DialogueLine dialogueline = new DialogueLine();
dialogueline.charactercode = charactercode;
dialogueline.line = line;
dialogueline.moodcode = moodcode;
SecondPerson listener = new SecondPerson();
listener.enabled = enabled;
listener.charactercode = listenercode;
listener.moodcode = listenermood;
dialogueline.listener = listener;
AdvancedLineOptions advanced = new AdvancedLineOptions();
dialogueline.advanced = advanced;
dialogues.Add(dialogueline);
}
dialogue.dialogues = dialogues.ToArray();
}
}
[System.Serializable]
public class DialoguesToImport
{
public string filepath;
public Dialogue dialogue;
}
this is totally error free and works totally perfect if i create a Dialogue object and feed it to this script through the to import array.... think i can work with making individual objects....the main problem is that i don't want to use characters to split it...and thanks again for all the help
it was not adding as a comment for some reason, so had to post this as separate answer
i searched up a bit and settled on using the Split(string[], options) format, however there is still one problem....."/n" is not working...everything else works, commas, strings and all other things, but i guess "/n" is not the actual representation of a line break
Follow this Question
Related Questions
Implementing a 2D array as a field on a ScriptableObject? 1 Answer
Organizing Recursive EditorGUI elements 1 Answer
Unable to serialize my list in a Unity Custom Editor script. 1 Answer
Trying to assign UI images from an array with scriptable objects not working? 1 Answer
Array of scriptable Objects inside scriptable Object reseting on Play 0 Answers