Search Unity

SOLVED - Getting info/string from .txt file

Discussion in 'Scripting' started by wilhelmscream, Jan 27, 2015.

  1. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    I'm curious - and there may not really be an answer in JS - about .txt files. A game I used to play drew names for ships from lists in .txt files, and I wonder how that would be done.

    The basic idea would be like this:

    You build a group of (let's say) battleships. Each one would have a unique name (Let's name them after states for this example). You have a .txt file (or any extraneous file, could be .doc or whatever) with a list of state names. As each ship is instantiated, it reads the text file, getting the next name in line and assigning it as the ship's name. Each name would only be used once, so the list would have to be changed each time, right?

    Am I over-thinking this or is this possible?
     
    soxdesigner likes this.
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Sure, it's entirely possible. I don't use JS, but in C#, you just use the standard built-in C# file classes.

    For example, here's a one-liner that gets the contents of a text file into an array of strings:

    Code (CSharp):
    1.         // Read each line of the file into a string array. Each element
    2.         // of the array is one line of the file.
    3.         string[] lines = System.IO.File.ReadAllLines(@"SomeFile.txt");
    4.  
    This would look for SomeFile.txt in the default directory, which is generally the directory containing the application. You can specify a full path if you have it.

    Instead of ReadAllLines, you could use ReadAllText if you want to get the contents of the file as one big string.

    HTH,
    - Joe
     
  3. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    I think that's in the general idea of what I'm looking for, thanks. It also (once again) reminds me I should have learned C# rather than JS :(
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well it's never too late. The languages are very similar, the docs do a great job of presenting both, and you can mix and match at your whim. So it's pretty easy to switch (or use both).
     
  5. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Yeah. I just have trouble translating one to the other.
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    All .NET functions are available in all languages. There's no problem using System.IO.File.ReadAllLines in JS.

    --Eric
     
    JoeStrout likes this.
  7. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    I can't find anything in the manual, tutorials, or script ref on this. Am I looking in the wrong place?
     
  8. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
    System.IO is a standard class that isn't in Unity's documentation.

    Refer to the MSDN documentations for this class, since the code is very similar.
     
  9. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
  10. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Think I'm just going to have to leave this aside, that stuff is waayyyy beyond my skill level. Just in case someone does know the answer, or can see where I'm going wrong, here's the code I have.....

    Code (JavaScript):
    1. var shipNameList : TextAsset;
    2. var shipName : String;
    3.  
    4. function Start () {
    5.      shipName = System.IO.File.ReadAllLines(shipNameList);
    6. }
    7.  
    8. function OnGUI () {
    9.      GUI.Label (Rect (10, 20, 100, 22), shipName.ToString ());
    10. }
     
    Last edited: Jan 28, 2015
  11. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
    If you only have one line use ReadAllText.
    And you don't need to call ToString on a String ;)
     
  12. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    I have several lines, each being intended to be used once, without repeat.

    All that code returns is "System.string []" rather than ANY of the lines.
     
  13. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    System.string[] is a string array, which contains all of the lines.

    --Eric
     
  14. gamer_boy_81

    gamer_boy_81

    Joined:
    Jun 13, 2014
    Posts:
    169
    Once you've read all the lines from the .txt file, you can use foreach to go through each line
    and do something with them like this :

    Code (CSharp):
    1. foreach(string line in shipName) {
    2.     Debug.Log("Ship name : " + line);
    3. }
     
  15. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Ok I see the array in the inspector now, Looks like I have to type each line in again, individually, which officially sucks fat monkey eggs. I still have no clue how to get it to choose just one line, and I already typed them all once in the text doc.
     
  16. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    I picked this up from a post a while ago, you just put your text file in a resources folder and then use these two lines:
    Code (csharp):
    1.  
    2. string f = Resources.Load ("msgDB").ToString(); // from Resources/msgDB.txt
    3. string[] msgDB = f.Replace("\r\n","\n").Replace("\r","\n").Split("\n"[0]);
    4.  
    I haven't actually tried it, but he said it worked. Don't know if it will work for your application.
     
  17. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Nope. That didn't solve it. Thanks though.
     
  18. gamer_boy_81

    gamer_boy_81

    Joined:
    Jun 13, 2014
    Posts:
    169
    Can you post the contents of your text file here ?
    I'm failing to understand for what looks like an otherwise easy
    thing to implement because we've been reading complex stuff
    from txt files and all of that works just fine.
     
  19. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    No, just read the file as a string array (not a string) and use the appropriate entry in the array.

    --Eric
     
  20. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    The text file is simply a list of names......

    Majestic
    Monarch
    Imperator
    Tyrant
    Imperious
    Regent

    etc etc..... a couple hundred lines worth


    That's what Ive been trying to do ...... but it's not reading anything, just creating an array with 0 elements.
     
  21. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
    Code (CSharp):
    1. string[] myFile = System.IO.File.ReadAllLines("myFile.txt");
    2. //DEBUG, NOT NEEDED
    3. foreach(string x in myFile){
    4. Debug.Log("Found name " + x);
    5. }
     
  22. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    It's reading the names just fine (as far as I can tell -- at least they are showing up in the inspector -- it's just not returning anything other than "System.string []". Ah well.
     
  23. gamer_boy_81

    gamer_boy_81

    Joined:
    Jun 13, 2014
    Posts:
    169
    Do you see a list of all the ship names one below the other OR you see them all
    in one single line ? (in the inspector that is)
     
  24. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Each below the other. 1 variable, 516 elements.
     
  25. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, that's what it supposed to return: an array of strings. Also known as String[]. It doesn't return String.

    --Eric
     
  26. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    I guess everything is working then. Pretty annoying to spend a week working on a problem that doesn't exist (or just doesn't have a solution, can't really tell which), no?
     
    Last edited: Feb 2, 2015
  27. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Marking this as solved, for lack of a better option. Thanks guys.
     
  28. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    What better option did you have in mind? ReadAllLines returns the contents of the text file as a string array, where each line is an entry in the array, which seems to be 100% exactly what you were asking for.

    --Eric
     
  29. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    What I was looking for was a way to have one entry in the array (first, last, random, doesn't matter) returned as the ship name and then removed from the array (to avoid reuse and make each one unique).
     
  30. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Convert the array to a list and use RemoveAt.

    --Eric
     
  31. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    So, assuming I wanted to start with the first entry on the list ...... it would look something like.....

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var textArray : String [] = System.IO.File.ReadAllLines("shipNameList.txt");
    4. var    nameArray : Array = new Array(textArray);
    5. var shipName : String;
    6.  
    7. function Start () {
    8.     nameArray.RemoveAt(1);
    9. }
    10.  
    11. function Update () {
    12. }
     
  32. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Don't ever use the Array class, use a List. Also, all code should be inside a function; only declare variables outside functions. All collections start with 0, not 1.

    Code (csharp):
    1. var nameList : List.<String>;
    2.  
    3. function Start () {
    4.     nameList = new List.<String>(System.IO.File.ReadAllLines("shipNameList.txt"));
    5.     nameList.RemoveAt (0);
    6. }
    --Eric
     
  33. chelnok

    chelnok

    Joined:
    Jul 2, 2012
    Posts:
    680
    Check this mini tuto about arrays:

    http://wiki.unity3d.com/index.php?title=Which_Kind_Of_Array_Or_Collection_Should_I_Use?

    You can get one line like this:

    myFile[0] would be the very first line
    myFile[1] would be second line
    myFile[ Random.Range( 5, 7 ) ] would be line 5 or 6
    myFile[ myFile.Lenght -1 ] would be the last line
     
  34. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Using this code.....

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var nameList : List.<String> = new List.<String>(System.IO.File.ReadAllLines("shipNameList.txt"));
    4. var shipName = nameList[0];
    5.  
    6. function Start () {
    7. }
    8.  
    9. function Update () {
    10. }
    Produces an error message

    "The name 'List' does not denote a valid type ('not found')."


    Trying it this way.....

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var nameList : List.<String>;
    4. var shipName = nameList[0];
    5.  
    6. function Start () {
    7.     nameList = new List.<String>(System.IO.File.ReadAllLines("shipNameList.txt"));
    8. }
    9.  
    10. function Update () {
    11. }
    12.  
    13. function OnGUI () {
    14.     GUI.Box (Rect (30, 30, 100, 25), shipName);
    15. }

    produces exactly the same problem. Seems like a good idea, but does JS not support Lists?
     
  35. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Sure it does, otherwise I would not have posted that code. Read the link chelnok posted about "what sort of array or collection should I use". Also, make sure you don't run code outside functions. (If you do, it will only run once, when the script is first created, which is almost never what you want.) You partially corrected that for the second version, but you need to fix it all.

    --Eric
     
  36. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    That's what I'm looking at. Is there an advantage to a generic list (what I'm trying to use here) over an ArrayList?
     
  37. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, the page linked to discusses all that. Short version: Never use JS Array or ArrayList.

    --Eric
     
  38. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,521
    I actually wasn't aware of ReadAllLines, so I made a C# version to check it out.

    For anyone else curious..

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections.Generic;
    4.  
    5. public class getNames : MonoBehaviour {
    6.  
    7.     public List<string> nameList;
    8.  
    9.     void Start () {
    10.  
    11.         nameList = new List<string>(System.IO.File.ReadAllLines("Assets\\Resources\\names.txt"));
    12.     }
    13.  
    14.     void OnGUI(){
    15.  
    16.         foreach (string s in nameList)
    17.         {
    18.             GUILayout.Label(s);
    19.         }
    20.     }
    21. }
    22.  
     
  39. wilhelmscream

    wilhelmscream

    Joined:
    Jun 5, 2013
    Posts:
    223
    Ok I have it down now. My apologies for being a pain in the ass, but it all works great, so lots of thanks for all the help.

    If interested, here's my now-functional code....

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. import System.Collections.Generic;
    4.  
    5. var nameList : List.<String>;
    6. var shipName : String;
    7. var hullNumber : int;
    8. var galMap : GameObject;
    9.  
    10. function Start () {
    11.     galMap = GameObject.FindGameObjectWithTag("GalMap");
    12.     SendMessageUpwards ("AddBSID", galMap, SendMessageOptions.RequireReceiver);
    13.     GetID ();
    14. }
    15.  
    16. function GetID () {
    17.     hullNumber = galMap.GetComponent(ShipProduction).battleshipID;
    18.     nameList = new List.<String>(System.IO.File.ReadAllLines("battleshipNameList.txt"));
    19.     GetShipName ();
    20. }
    21.  
    22. function GetShipName () {
    23.     shipName = nameList[hullNumber];
    24. }
    25.  
    26. function Update () {
    27. }
     
    MD_Reptile likes this.