Ok, I finally took the plunge into C# from JS tonight and I’m feeling a little like someone just turned the lights out on me. I’m trying to make a text file reader that will read the file line by line, but I can only figure out how to read the whole text in one go using this modified script from an O’Reilly book I picked up at the library today.
using UnityEngine;
using System.Collections;
using System;
using System.IO;
public class LineReader : MonoBehaviour
{
void Start ()
{
FileInfo theSourceFile = new FileInfo ("Test.txt");
StreamReader reader = theSourceFile.OpenText();
string text;
do
{
text = reader.ReadLine();
//Console.WriteLine(text);
print (text);
} while (text != null);
}
}
I generally understand how this script is working as it loops through the text file until it comes to the end, but I don’t know how to just isolate “text = reader.ReadLine();” and just make it read one line at a time during an Update. Which brings up my second problem.
I don’t understand how to open the text file in the Start and then reference it in the Update. If I put the whole thing in the Update it tries to open the text file every frame and causes problems.
If someone could please treat me like the coding infant that I am and walk me through how to do this I’d really appreciate it.
-Ethan
I’m a beginner at C#, but I’ve coded C/C++ and Java for years, so I’ll have a stab at this.
If you define the variables outside of individual functions, the scope will allow them to be seen anywhere in the class. The code below should do what you want:
using UnityEngine;
using System.Collections;
using System;
using System.IO;
public class LineReader : MonoBehaviour
{
protected FileInfo theSourceFile = null;
protected StreamReader reader = null;
protected string text = " "; // assigned to allow first line to be read below
void Start () {
theSourceFile = new FileInfo ("Test.txt");
reader = theSourceFile.OpenText();
}
void Update () {
if (text != null) {
text = reader.ReadLine();
//Console.WriteLine(text);
print (text);
}
}
}
1 Like
Hey hey, thanks a bundle spaniard! That does the reading inside the Update perfectly. So “protected” implies what exactly? Does it just make it global to the script?
Well, I really need to familiarize myself with this new syntax in C# before I just start spouting off a bunch of questions… but just a couple more 
How can I get it to read the text file in a continuous loop instead of just ending at the end of the text file?
Also, I need to read each line in the file at a specific time rate (BPM tempo). Any pointers in the right direction for this would be great… And more in the “teach a man to fish” vein of how it’s working so I can learn how to “feed” myself in the long run.
Thanks again spaniard, I’ll try to milk as much knowledge as I can from your example script.
I’m all about fishing, so I’ll try not to hand you the fish next time…
The protected keyword is used to define who can access the variable; the other options are public and private.- public: the variable can be seen and changed by anyone that can see the class.
- private: the variable cannot be seen or changed except within the class
- protected: the variable can be seen by anyone, but only changed by the class that owns it
There are also issues of inheritance, i.e. classes derived from this class and how they can see those types of variables, but we’ll save that for another day…
I had chosen protected since you may want to access the current line from the file with some other code, but to be safe, we don’t want to let anyone else change its value.
As for looping the reading of the file, you could add an else clause in the Update method to reopen the file. Let me know if you would like some example code.
And with reading at a particular rate, I’d wrap the entire content of the Update method in an if statement to test if this frame is one that we should read a line in. You would probably want to use something from the Time class to test that.
As a side note, I hope you don’t need this code and that someone can implement the MIDI code that you’re looking for - that would be pretty cool.
Don’t get me wrong, the fish was delicious 
Right on the money, this script will hopefully be a master track that a bunch of other scripts will derive their variables from.
Is it really necessary to reopen the file every time you read through it? I read tonight in the C# book about reading the text into a buffer. Maybe that would be more effecient as these tracks/texts could get pretty big for a 5 minute song?
Yeah, I just need to figure out the formula for Time.DletaTime to spit out a framerate equalling the tempo.
Well, I’m starting to think that finding a match with someone talented enough to code the MIDI plug-in and that also needs my art skills is going to be very rare (simply because someone able to do this is probably working on a proffessional level and already has a dedicated artist on their team). Plus, using this text method I’m not limited to the 7-bit world of MIDI. 0-127 iterations can be choppy when translated into 3D transforms.
Thanks for furthering me along here, you’re insights are great.
I’m not sure that a buffer is the solution you’re looking for, since buffers usually throw out data as soon as you’ve read it. It may still be useful, but ultimately not what you’re looking for.
What you could do is store the lines in an array and then loop through the lines. This would mean you would read everything into the array in Start and then Update only needs to get the line from the array. Depending on how many lines you’re talking about, this could work.
As another thought, you do need to close the file when you’re done reading from it, which you could do at the moment using a descructor:
~LineReader () {
reader.Flush();
reader.Close();
}
The tilde(~) before the name of the class makes it a descructor, i.e. called when the object is destroyed. If the array approach made sense, then you would close the reader after loading it into the array and you wouldn’t need the destructor.
Did you say that you want to sync the framerate to BPM? From a graphical point of view, that sounds like a bad idea since the framerate would average 2fps, a bit slow. You could use FixedUpdate as that updates very frequently and at a fixed time. You could presumably alter the interval for fixed updates (Fixed Timestep in the Time Manager). My guess is to access it through Time.fixedDeltaTime but I’m not sure that you can change the value of that through a script.
I’d love to help out on the plugin, but I really don’t think I have the expertise to pull it off.
Not quite. A protected variable will only be accessible to the class or types derived hereof. To get the effect read-only effect you can make a property instead.
public class MyNumber {
private int someNumber;
public int number {
get {
return someNumber;
}
}
}
If you want to, you can also allow setting the number. E.g.
public class MyNumber {
private int someNumber;
public int number {
get {
return someNumber;
}
set {
if (value > 0)
someNumber = value;
}
}
}
would allow anybody to read variable, but only allow them to set it to positive values. E.g.
MyNumber n = new MyNumber();
n.someNumber = 5;
n.someNumber = -4;
Debug.Log(n.someNumber);
will output 5.
I PM’d you some code that might help
-Jeremy
Good call Talzor, I had that wrong. Not sure how I managed to have a lapse with something so basic…