Search Unity

CSV data and properties

Discussion in 'Scripting' started by Stefanovicz, Apr 16, 2018.

  1. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Hello community!

    I need your help.

    I am not a pro in coding but when I have a problem, I dig for solutions on Internet and give a try. Usually, I work out something and can go on. But now, I am completely stuck and can't find a proper solution for my issue. So...

    I am working on a Risk-like game (still early in development) I made a world map with territories. Everything was fine until now. The problem is that I have a CSV file with all the data of each territory (name, country, size, population, etc.). Since a territory is a sprite, I attached a script with public attributes. I would like to fill these attributes with the data of my CSV file according to the name of the territory.

    I found different solution in reading/writing CSV files but none work for what I'm looking for. I am sure that there is a way to achieve it but can't find a proper one.

    I hope I have been clear enough

    Thanks in advance

    Stefano
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Unless you are forced to use CSV, I would suggest json instead and looking into either Unity's JsonUtility or a different json serialization asset like json.net.

    Nothing against CSV, I just find json easier to work with.

    Otherwise, I'm sure you could find some premade script for csv or you could write one yourself.
     
  3. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    if this is your csv,
    territoryname, country, size, population, etc
    green, usa, 80000, 200, 123
    red, russia, 10000, 600, bla
    yello, china, 1100000, 700, what

    you read the file and store each line as a string array.
    then break up each element of the based on the "," then remove all blank spaces.
    then each of these elements can be bushed to you're sprite script.

    I'll try and find a script
     
  4. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Hello, thanks for your replies

    @Brathnann i don't really know how to use Json so I'm not sure I could achieve that.

    @johne5 it is exactly what I tried to do. I found infos about CSV reader but then I am missing something.
     
  5. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    it's not tested, but It should get in the right direction

    using System.Collections.Generic;
    using System.IO;
    Code (CSharp):
    1. class SomeClass
    2.     {
    3.         private List<string> stringList;
    4.         private List<string[]> parsedList;
    5.  
    6.  
    7.         void Start()
    8.         {
    9.             readTextFile();
    10.         }
    11.  
    12.         void readTextFile()
    13.         {
    14.             StreamReader inp_stm = new StreamReader("Assets/Resorces/worldData.csv");
    15.  
    16.             while (!inp_stm.EndOfStream)
    17.             {
    18.                 string inp_ln = inp_stm.ReadLine();
    19.  
    20.                 stringList.Add(inp_ln);
    21.             }
    22.  
    23.             inp_stm.Close();
    24.  
    25.             parseList();
    26.         }
    27.  
    28.         void parseList()
    29.         {
    30.             for (int i = 0; i < stringList.Count; i++)
    31.             {
    32.                 string[] temp = stringList[i].Split(",");
    33.                 for (int j = 0; j < temp.Length; j++)
    34.                 {
    35.                     temp[j] = temp[j].Trim();  //removed the blank spaces
    36.                 }
    37.                 parsedList.Add(temp);
    38.             }
    39.             //you should now have a list of arrays, ewach array can ba appied to the script that's on the Sprite
    40.             //you'll have to figure out a way to push the data the sprite
    41.             SpriteScript.Name = parsedList[0];
    42.             SpriteScript.country = parsedList[1];
    43.             SpriteScript.size = parsedList[2];
    44.             SpriteScript.population = parsedList[3];
    45.         }
    46.     }
     
  6. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    okay!
    I tried your code and we're getting closer, thank you. But I still have a couple of errors.
    The first ones are CS1502 CS1503 (seem to be some kind of problem of conversion string-char that I already had with other codes I tried [line in bold]) :

    void parseList()
    {
    for (int i=0; i < stringList.Count; i++)
    {
    string[] temp = stringList .Split (",");
    for (int j = 0; j < temp.Length; j++)
    {
    temp [j] = temp [j].Trim ();//removed the blank spaces
    }
    parsedList.Add(temp);
    }

    and the second one that I have for each property at the end of the code:

    rm.Nom = parsedList [0];

    CS0029: Cannot implicitly convert type `string[]' to `string'

    Sorry it's a little bit messy ahaha
    Do you see what I'm missing?

    Thanks already for your help
     
  7. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Json is super easy and worth learning. And honestly, would be much better than csv.

    Also, please use code tags! It's a pain to read code without it.
    The first error is your split. That version takes a char, which means you use ',' instead of ","

    Code (CSharp):
    1. string[] temp = stringList.Split(',');
    The next issue is your parsedList is adding an array of strings to a list.

    rm.Nom = parsedList[0] is trying to set an array of strings into a string value, so it doesn't work.
     
  8. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
  9. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    you can try
    string[] temp = stringList.Split(","[0])

    you also had a space: stringList .Split

    you're correct it's an array inside a list.
    SpriteScript.Name = parsedList[0][0];
    SpriteScript.country = parsedList[0][1];
    SpriteScript.size = parsedList[0][2];
    SpriteScript.population = parsedList[0][3];
     
  10. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Thank you everybody, I had to do some minor changes but it works know :)
     
  11. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    good news. glad you got it working.
    Any change you can post the final code?
     
  12. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    yes sure!

    here it is (i mixed what you told me and what I already had):

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. class CSVReader : MonoBehaviour
    6. {
    7.     public string Nom;
    8.     public string Pays;
    9.     public float Superficie;
    10.     public float Population;
    11.     public float CroissancePopulation;
    12.     public float PIB;
    13.     public float CroissancePIB;
    14.     public string Langue;
    15.     public string Religion;
    16.  
    17.  
    18.     List<Region> regions = new List<Region>();
    19.  
    20.     void Start()
    21.     {
    22.         TextAsset DataCSV = Resources.Load<TextAsset> ("DataCSV");
    23.  
    24.         string[] line = DataCSV.text.Split (new char[] { '\n' });
    25.  
    26.         for(int i = 1; i < line.Length-1; i++)
    27.         {
    28.             string[] part = line [i].Split (new char[]{ ';' });
    29.  
    30.             if (part[0] == gameObject.name)
    31.             {
    32.                 Region region = new Region ();
    33.                 Nom =  part [0];
    34.                 Pays = part [1];
    35.                 float.TryParse (part [2], out Superficie);
    36.                 float.TryParse (part [3], out Population);
    37.                 float.TryParse (part [4], out CroissancePopulation);
    38.                 float.TryParse (part [5], out PIB);
    39.                 float.TryParse (part [6], out CroissancePIB);
    40.                 Langue = part [7];
    41.                 Religion = part [8];
    42.  
    43.                 regions.Add(region);  
    44.             }
    45.         }
    46.     }
    47. }
    thanks again, next step will be to write new properties as they may change, like population
     
  13. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    This is great, I see you're even doing a TryParse to extract a number instead of a string.
    Looks like I had the Splitting of the string wrong.

    Thanks for posting.
     
  14. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Thank you!
    I learn little by little but then it's so pleasant when it finally works ahah
     
  15. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Hello again!

    I come back here since there is something that I don't get right.

    In an other script (not the one I wrote above) I try to get in a new list called Pays (=country) the data from the script above.

    Here is the script:

    Code (CSharp):
    1. public string paysliste;
    2.     public List<string> Pays = new List<string> ().Distinct().ToList();
    3.  
    4.     void Start()
    5.     {
    6.         foreach(var i in CSVReader.Instance.regions)
    7.         {
    8.             paysliste = CSVReader.Instance.Pays;
    9.             Pays.Add (paysliste);
    10.         }
    11.  
    12.         Debug.Log (Pays);
    The problem is that in the debug, I don't have the name of the countries but I get this: Capture.PNG

    I get 571 same messages which are the correct number of my territories but why not the names of the countries?
    + I tried to use Distinct().toList() to avoid duplicates but since I get 571 messages, it seems that it doesn't work.

    Thanks in advance
     
  16. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,539
    You say:
    Code (csharp):
    1. Debug.Log (Pays);
    You've printed the List object. Which when converted to string (ToString is called on it), it just prints out the name of the type of the object it is.

    The List is a collection of strings, not a string itself.

    You must loop over it to get all the strings inside of it.

    Something like:
    Code (csharp):
    1.  
    2. foreach(var s in Pays)
    3. {
    4.     Debug.Log(s);
    5. }
    6.  
    Which would print multiple lines for each entry.

    If you wanted to say print it as one long line separated by commas you could do something like:
    Code (csharp):
    1. Debug.Log(string.Join(", ", Pays));
     
  17. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    @lordofduct that was my thought to. he creates a var i, but never uses it.

    Code (CSharp):
    1. void Start()
    2.     {
    3.         foreach(var i in CSVReader.Instance.regions)
    4.         {
    5.             paysliste = i.Instance.Pays;
    6.             //or maybe, paysliste = i.Pays;
    7.             Pays.Add (paysliste);
    8.         }
    9.         Debug.Log (Pays); //but this is a List<> so you can't print it like this.
    10.         Debug.Log (Pays[0]);  //we are assuming this is a List<string>,  because you put a string into it.
     
  18. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Hi!

    Thanks for your replies!

    Okay, I changed my code as you both told me. It's better but still... I get 571 time "Null" and not the names of the countries. Do you see what I am missing?
    Sorry, as I told before, I'm learning little by little :)
     
  19. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    Can you please paste the null ref so we can look at it.
     
  20. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Sure:

    Null
    UnityEngine.Debug:Log(Object)
    ColorManager:Start() (at Assets/Scripts/ColorManager.cs:45)

    and line 45 is the Debug:

    Code (CSharp):
    1.        
    2.  
    3. foreach(var s in ListPays)
    4.         {
    5.             Debug.Log (s);
    6.         }
    7.  
     
  21. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. class CSVReader : MonoBehaviour
    5. {
    6.     public string Nom;
    7.     public string Pays;
    8.     public float Superficie;
    9.     public float Population;
    10.     public float CroissancePopulation;
    11.     public float PIB;
    12.     public float CroissancePIB;
    13.     public string Langue;
    14.     public string Religion;
    15.     public List<Region> regions = new List<Region>(); //changed from private to public
    16.  
    17.     void Start()
    18.     {
    19.         TextAsset DataCSV = Resources.Load<TextAsset> ("DataCSV");
    20.         string[] line = DataCSV.text.Split (new char[] { '\n' });
    21.         for(int i = 1; i < line.Length-1; i++)
    22.         {
    23.             string[] part = line [i].Split (new char[]{ ';' });
    24.             if (part[0] == gameObject.name)
    25.             {
    26.                 Region region = new Region ();  //create a new blank region
    27.                 Nom =  part [0];
    28.                 Pays = part [1];
    29.                 float.TryParse (part [2], out Superficie);
    30.                 float.TryParse (part [3], out Population);
    31.                 float.TryParse (part [4], out CroissancePopulation);
    32.                 float.TryParse (part [5], out PIB);
    33.                 float.TryParse (part [6], out CroissancePIB);
    34.                 Langue = part [7];
    35.                 Religion = part [8];
    36.                 regions.Add(region);  //add blank region to the list
    37.             }
    38.         }
    39.     }
    40. }
    41.  
    42. public string paysliste;
    43. public List<string> Pays = new List<string> ().Distinct().ToList();
    44.  
    45. void Start()
    46.     {
    47.         CSVReader csvReader = gameObject.GetComponent<CSVReader>();
    48.         foreach(var i in csvReader.regions)
    49.         {
    50.             paysliste = i.Pays; // i think this is null, per if statement starting at line 31
    51.             Pays.Add (paysliste);
    52.         }
    53.         Debug.Log (Pays.Count); //display how many where added to the list
    54.  
    55.     }
     
  22. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    Where are you getting ListPays from? I don't see it in your code.
    It's coming from the ColorManager script
     
  23. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    oh yes, sorry, I renamed the list Pays by ListPays since I already have the variable Pays in CSVReader

    Actually, I should explain myself:
    with this new script, I am trying to create a list with the names of the countries (since I already have the data in CSVReader I'd like to link the two scripts) in order to assign a colour for each country.

    PS: with the Debug.Log(Pays.Count) that you posted above, I get 571 time "1" in the console.
     
    Last edited: Apr 25, 2018
  24. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Okay soooo...

    I wrote a new script since I was getting lost with the previous one. I think I am close:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using System.Linq;
    6.  
    7. [RequireComponent(typeof(PolygonCollider2D))]
    8.  
    9. public class NewColorManager : MonoBehaviour {
    10.  
    11.     public List<Color> colors = new List<Color> ();
    12.  
    13.     private SpriteRenderer sprite;
    14.  
    15.     public string paysliste;
    16.     public List<string> ListPays = new List<string>().Distinct().ToList();
    17.  
    18.     //private Color32 hoverColor;
    19.     private Color32 startColor;
    20.  
    21.  
    22.     // Use this for initialization
    23.     void Start ()
    24.     {
    25.         CSVReader csvReader = gameObject.GetComponent<CSVReader> ();
    26.         paysliste = csvReader.Pays;
    27.         ListPays.Add (paysliste);
    28.  
    29.         foreach( in ListPays)
    30.         {
    31.             startColor = new Color (Random.value, Random.value, Random.value, 0.5f);
    32.             sprite = GetComponent<SpriteRenderer> ();
    33.             if (!colors.Contains(startColor))
    34.             {
    35.                 sprite.color = startColor;
    36.                 colors.Add (startColor);
    37.             }
    38.         }
    39.  
    40.         Debug.Log (paysliste);
    41.     }
    42.  
    So I am close but it seems that on line 16 the Distinct().toList() doesn't delete the duplicates and on line 29, how can I set foreach name of country?

    Anyway, thanks a lot
     
  25. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    from what I know, You have 3 scripts, ColorManager, Region, CSVReader.
    Can you show us the Region script?
    we have not seen the region script. I still believe the main issue is in the CSVReader script. In this script you are populating the List<Region>. I only see you adding blank data.

    I'm looking over the new script. i'll get back to you in a sec
     
  26. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Okay, the script Region is just a public class:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class Region
    7. {
    8.     public string Nom;
    9.     public string Pays;
    10.     public float Superficie;
    11.     public float Population;
    12.     public float CroissancePopulation;
    13.     public float PIB;
    14.     public float CroissancePIB;
    15.     public string Langue;
    16.     public string Religion;
    17. }
    18.  
    But when I hit Play, the properties of each gameobject / territory fill themselves properly as shown in the picture below:
    Capture.PNG
     
  27. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    Let me know if this helps

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5. [RequireComponent(typeof(PolygonCollider2D))]
    6. public class NewColorManager : MonoBehaviour {
    7.     public List<Color> colors = new List<Color> ();
    8.     private SpriteRenderer sprite;
    9.     public string paysliste;
    10.     public List<string> ListPays;
    11.     //private Color32 hoverColor;
    12.     private Color32 startColor;
    13.     // Use this for initialization
    14.     void Start ()
    15.     {
    16.         ListPays = new List<string>().Distinct().ToList(); //set the list here may help.
    17.         CSVReader csvReader = gameObject.GetComponent<CSVReader> ();
    18.         if(!csvReader)
    19.         {
    20.             //csvReader is null,  stop running the script
    21.             Debug.Log("CSVReader is NULL");
    22.             return;
    23.         }
    24.        
    25.         paysliste = csvReader.Pays;  //set paysliste from CSVReader script
    26.         ListPays.Add (paysliste); // add this paysliste to the list
    27.         Debug.Log("Number of ListPays : " + ListPays.Count);
    28.         //foreach( in ListPays) //there is only 1 entry in the list,  also missing an element
    29.         foreach(string payee in ListPays)
    30.         {
    31.             startColor = new Color (Random.value, Random.value, Random.value, 0.5f); //get a random color
    32.             sprite = GetComponent<SpriteRenderer> (); //find the render
    33.             if (!colors.Contains(startColor)) //if the startColor is not in the list of colors, then lets add it to the list and change this object to the new color
    34.             {
    35.                 sprite.color = startColor;
    36.                 colors.Add (startColor);
    37.             }
    38.         }
    39.         Debug.Log (paysliste); //not sure why you're checking this
    40.     }
    41.  
     
  28. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    in CSVReader, needs to look like this

    Code (CSharp):
    1. for(int i = 1; i < line.Length-1; i++)
    2.         {
    3.             string[] part = line [i].Split (new char[]{ ';' });
    4.             if (part[0] == gameObject.name)
    5.             {
    6.                 Region region = new Region ();
    7.                 region.Nom =  part [0]; //Nom
    8.                 region.Pays = part [1];
    9.                 float.TryParse (part [2], out region.Superficie);
    10.                 float.TryParse (part [3], out region.Population);
    11.                 float.TryParse (part [4], out region.CroissancePopulation);
    12.                 float.TryParse (part [5], out region.PIB);
    13.                 float.TryParse (part [6], out region.CroissancePIB);
    14.                 region.Langue = part [7];
    15.                 region.Religion = part [8];
    16.                 regions.Add(region);
    17.             }
    18.         }
     
  29. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    I tried your code and here what I get:
    Capture.PNG
    Correct me if I'm wrong but it seems that instead of having one list of 571 elements I have 571 lists of 1 element.. maybe that's the problem
     
  30. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    how many gameObject is CSVReader attached to?
    how many gameObjects is colorManager attached to?

    you should not be getting 500+ messages
     
  31. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    yeah, I attached them to all the 571 territories... this is the problem right ?
     
  32. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    yep, Let me think about what you're end goal is. I'll try and get you some code. It will take me some time.
     
  33. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    None of this is tested, I'll test it when I get home tonight.

    No change to the Region script
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class Region
    5. {
    6.     public string Nom;
    7.     public string Pays;
    8.     public float Superficie;
    9.     public float Population;
    10.     public float CroissancePopulation;
    11.     public float PIB;
    12.     public float CroissancePIB;
    13.     public string Langue;
    14.     public string Religion;
    15. }
    You need an empty gameObject and place the CSVReader and ColorManager on it
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class CSVReader : MonoBehaviour
    5. {
    6.     //public string Nom;
    7.     //public string Pays;
    8.     //public float Superficie;
    9.     //public float Population;
    10.     //public float CroissancePopulation;
    11.     //public float PIB;
    12.     //public float CroissancePIB;
    13.     //public string Langue;
    14.     //public string Religion;
    15.     //this is our public list for all other gameObject to use
    16.     public List<Region> regions = new List<Region>();
    17.     void Start()
    18.     {
    19.         TextAsset DataCSV = Resources.Load<TextAsset> ("DataCSV");
    20.         string[] line = DataCSV.text.Split (new char[] { '\n' });
    21.         for(int i = 1; i < line.Length-1; i++)
    22.         {
    23.             string[] part = line [i].Split (new char[]{ ';' });
    24.             if (part[0] == gameObject.name)
    25.             {
    26.                 Region region = new Region ();
    27.                 region.Nom =  part [0];
    28.                 region.Pays = part [1];
    29.                 float.TryParse (part [2], out region.Superficie);
    30.                 float.TryParse (part [3], out region.Population);
    31.                 float.TryParse (part [4], out region.CroissancePopulation);
    32.                 float.TryParse (part [5], out region.PIB);
    33.                 float.TryParse (part [6], out region.CroissancePIB);
    34.                 region.Langue = part [7];
    35.                 region.Religion = part [8];
    36.                 regions.Add(region);
    37.             }
    38.         }
    39.        
    40.         Debug.Log("CSVReader Region Count : " + regions.Count);
    41.     }
    42. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ColorManager : MonoBehaviour
    6. {
    7.     public List<Color> colors = new List<Color> ();
    8. }
    A new script that gets placed on the 500+ objects
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5. [RequireComponent(typeof(PolygonCollider2D))]
    6. public class SetColor : MonoBehaviour
    7. {
    8.     private SpriteRenderer sprite;
    9.    
    10.     private Color32 startColor;
    11.     void Start ()
    12.     {
    13.         ColorManager colorManager = FindObjectsOfType<ColorManager>();
    14.         CSVReader csvReader = FindObjectsOfType<CSVReader>();
    15.  
    16.         if(!colorManager)
    17.         {
    18.             Debug.Log("colorManager is NULL");
    19.             return;
    20.         }
    21.        
    22.         if(!csvReader)
    23.         {
    24.             Debug.Log("csvReader is NULL");
    25.             return;
    26.         }
    27.  
    28.         foreach(Region region in csvReader.regions)
    29.         {
    30.             if (region.Nom == gameObject.name)
    31.             {
    32.                 startColor = new Color (Random.value, Random.value, Random.value, 0.5f);
    33.                 sprite = GetComponent<SpriteRenderer> ();
    34.                 if (!colorManager.colors.Contains(startColor))
    35.                 {
    36.                     sprite.color = startColor;
    37.                     colorManager.colors.Add (startColor);
    38.                 }
    39.             }
    40.         }
    41.     }
    42. }
     
  34. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    I did have few mistakes. But I've got working in my test scene. the sprites in the scene change to a new color every time the scene is ran.
    attached screen shot and scripts.
    if you don't want to replace the 500+ objects with the SetColor script, then you'll need to modify my code to look for the new script that stores the color list.
     

    Attached Files:

  35. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Hi !

    Firstly, thank you so much for your help and your time!!!

    I tried your code and it works fine but... I still miss what I'm looking for. I apologize I haven't been clear enough. The thing is that most of the countries are split in some territories. With my previous code and with yours, all the territories have a colour but colours should apply on countries not territories (for example, all the territories with the country name "Italy" should have the same colour) if you see what I mean.
    I must add a condition somewhere but I can find out how. I have trouble linking the scripts together.

    Thanks again for your help, it's very welcome.
     
  36. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    it's an easy fix.

    here are the updated scripts, with some notes.
    My Scripts assume that Nom is the Country name

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Region
    6. {
    7.     public string Nom;
    8.     public string Pays;
    9.     public float Superficie;
    10.     public float Population;
    11.     public float CroissancePopulation;
    12.     public float PIB;
    13.     public float CroissancePIB;
    14.     public string Langue;
    15.     public string Religion;
    16.     public Color color; //added a color
    17. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5. [RequireComponent(typeof(PolygonCollider2D))]
    6. public class SetColor : MonoBehaviour
    7. {
    8.     private SpriteRenderer sprite;
    9.  
    10.     private Color32 startColor;
    11.     void Start()
    12.     {
    13.         ColorManager colorManager = FindObjectOfType<ColorManager>();
    14.         CSVReader csvReader = FindObjectOfType<CSVReader>();
    15.  
    16.         if (!colorManager)
    17.         {
    18.             Debug.Log("colorManager is NULL");
    19.             return;
    20.         }
    21.  
    22.         if (!csvReader)
    23.         {
    24.             Debug.Log("csvReader is NULL");
    25.             return;
    26.         }
    27.  
    28.         foreach (Region region in csvReader.regions)
    29.         {
    30.             if (region.Nom == gameObject.name)
    31.             {
    32.                 if (region.color == Color.black) //check if the color was set
    33.                 {
    34.                     //the color has not been set yet.
    35.                     startColor = new Color(Random.value, Random.value, Random.value, 0.5f); //get a new color
    36.                     if (!colorManager.colors.Contains(startColor)) //check if the new random color is in the color list
    37.                     {
    38.                         colorManager.colors.Add(startColor); // it's not in the color list so we add it to the list
    39.                         region.color = startColor; // set the color in the regions list
    40.                     }
    41.                 }
    42.              
    43.                 sprite = GetComponent<SpriteRenderer>();
    44.                 sprite.color = region.color; //set the color to the color that was stored in the list
    45.             }
    46.         }
    47.     }
    48. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class CSVReader : MonoBehaviour
    5. {
    6.     //this is our public list for all other gameObject to use
    7.     public List<Region> regions = new List<Region>();
    8.     void Awake()
    9.     {
    10.         Debug.Log("Read the CSV file");
    11.         TextAsset DataCSV = Resources.Load<TextAsset>("DataCSV");
    12.         string[] line = DataCSV.text.Split(new char[] { '\n' });
    13.  
    14.         for (int i = 0; i < line.Length; i++)
    15.         {
    16.             string[] part = line[i].Split(new char[] { ';' });
    17.  
    18.                 Region region = new Region();
    19.                 region.Nom = part[0];
    20.                 region.Pays = part[1];
    21.                 float.TryParse(part[2], out region.Superficie);
    22.                 float.TryParse(part[3], out region.Population);
    23.                 float.TryParse(part[4], out region.CroissancePopulation);
    24.                 float.TryParse(part[5], out region.PIB);
    25.                 float.TryParse(part[6], out region.CroissancePIB);
    26.                 region.Langue = part[7];
    27.                 region.Religion = part[8];
    28.                 region.color = new Color(0,0,0,1); //sets a default color to black
    29.  
    30.                 regions.Add(region);
    31.        
    32.         }
    33.  
    34.         Debug.Log("CSVReader Region Count : " + regions.Count);
    35.         foreach(Region region in regions)
    36.         {
    37.             //Debug.Log("Nom: " + region.Nom + ", Pays: " + region.Pays + ", Superficie: " + region.Superficie + ", Population: " + region.Population + ", C-Population: " + region.CroissancePopulation + ", PIB: " + region.PIB + ", C-PIB: " + region.CroissancePIB + ", Langue: " + region.Langue + ", Religion: " + region.Religion);
    38.         }
    39.     }
    40. }
     
  37. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Hey,

    Thanks again, I tried it but it still the same (one colour for each territory, not each country). The thing is that "Nom" is the name of the territory so I must use "Pays" which is the name of the country.
    I tried to add a foreach loop with the variable Pays (see code below) but I get an error on it (cannot convert type 'char' to 'Region')
    I guess I have trouble on how tu use my data from the CSVReader and the Region script.

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using System.Linq;
    6.  
    7. [RequireComponent(typeof(PolygonCollider2D))]
    8.  
    9. public class SetColor : MonoBehaviour
    10. {
    11.     private SpriteRenderer sprite;
    12.  
    13.     private Color32 hoverColor;
    14.     private Color32 startColor;
    15.  
    16.     public Region region; //I add this to use it below in the foreach loop
    17.  
    18.     void Start()
    19.     {
    20.  
    21.         ColorManager colorManager = FindObjectOfType<ColorManager> ();
    22.         CSVReader csvReader = FindObjectOfType<CSVReader> ();
    23.  
    24.         if (!colorManager)
    25.         {
    26.             Debug.Log ("colorManager is NULL");
    27.             return;
    28.         }
    29.  
    30.         if (!csvReader) {
    31.             Debug.Log ("csvReader is NULL");
    32.             return;
    33.         }
    34.  
    35.         foreach (Region region in csvReader.regions)
    36.         {
    37.             if(region.Nom == gameObject.name)
    38.             {
    39.                 foreach(Region pays in region.Pays) //i thought by adding this it would iterate through all my country names (=Pays)
    40.                 {
    41.                     if(region.color == Color.black)
    42.                     {
    43.                        
    44.                         startColor = new Color (Random.value, Random.value, Random.value, 0.5f);
    45.                         if (!colorManager.colors.Contains (startColor) && startColor != new Color(255,255,255,1))
    46.                         {
    47.                             colorManager.colors.Add (startColor);
    48.                             region.color = startColor;
    49.                         }
    50.                     }
    51.                 }
    52.                 sprite = GetComponent<SpriteRenderer> ();
    53.                 sprite.color = startColor;
    54.             }
    55.         }
    56.     }
     
  38. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    just change line 37,
    1. foreach (Region region in csvReader.regions)
    2. {
    3. if(region.Pays== gameObject.name) //change this line to Pays
    4. {
    remove the if statement you created
     
  39. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    the peace of the project i'm missing.
    what are the names of the gameObjects? the script is checking , if my name is the same as Pays name, then set my color,

    Can you post a screen shot of the gameObjects
     
  40. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    Do you have a gameObject that is a main country with the territories as children gameObjects?
     
  41. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    okay okay, we're getting closer ahaha
    so I changed line 37 and removed the if statement.
    The names of the gameObjects are the names of the territories .
    Exactly, some countries are only composed by one territory (ie. the territory have the same "Nom" and "Pays"). These ones are getting a colour as they should. On the other hand, the countries that are composed of various territories (ie. the name of the territories are not the same of the country they belong to) are not getting coloured.
    Yes, I put all my territories in one empty gameObject called "Regions"

    That is why, at the beggining I tried to create a list of unique countries' name (=Pays), I wanted to get a collection of all the countries name and set a colour for each of them.

    I don't know if I'm clear.
     
    Last edited: Apr 28, 2018
  42. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    So I edited the script for child parent structure
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5. [RequireComponent(typeof(PolygonCollider2D))]
    6. public class SetColor : MonoBehaviour
    7. {
    8.     private SpriteRenderer sprite;
    9.  
    10.     private Color32 startColor;
    11.     void Start()
    12.     {
    13.         ColorManager colorManager = FindObjectOfType<ColorManager>();
    14.         CSVReader csvReader = FindObjectOfType<CSVReader>();
    15.  
    16.         if (!colorManager)
    17.         {
    18.             Debug.Log("colorManager is NULL");
    19.             return;
    20.         }
    21.  
    22.         if (!csvReader)
    23.         {
    24.             Debug.Log("csvReader is NULL");
    25.             return;
    26.         }
    27.  
    28.         foreach (Region region in csvReader.regions)
    29.         {
    30.             if (region.Pays == gameObject.transform.parent.name) // this line was changed
    31.             {
    32.                 if (region.color == Color.black) //check if the color was set
    33.                 {
    34.                     //the color has not been set yet.
    35.                     startColor = new Color(Random.value, Random.value, Random.value, 0.5f); //get a new color
    36.                     if (!colorManager.colors.Contains(startColor)) //check if the new random color is in the color list
    37.                     {
    38.                         colorManager.colors.Add(startColor); // it's not in the color list so we add it to the list
    39.                         region.color = startColor; // set the color in the regions list
    40.                     }
    41.                 }
    42.                
    43.                 sprite = GetComponent<SpriteRenderer>();
    44.                 sprite.color = region.color; //set the color to the color that was stored in the list
    45.             }
    46.         }
    47.     }
    48. }
     
  43. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    screen shots of my scene s39_screenshot_2.PNG s39_screenshot_1.PNG
     
  44. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Ooooh okay I see now
     
  45. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    So it sounds like you need to create a country for the territories that only have 1 territory
     
  46. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Yes, I am creating gameObjects for all the countries.
    But we're okay, I will be able in the future to change the hierarchy if a territory's country change (after a battle for example) ?
    I let you know how it works when I am finished creating gameObjects
     
  47. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    After the color change part is completed, what's next? Click on territory and do something?
     
  48. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    yes, I will do the "interactions" with the mouse.

    Thank you sooo much !!! It finally works !!! ahahha that one was hard to set, thanks!
     
    Last edited: Apr 29, 2018
  49. Stefanovicz

    Stefanovicz

    Joined:
    Jan 28, 2015
    Posts:
    57
    Hello there !

    After a long time I could not work on my project, I'm back... with an issue ;) !

    I changed something in my CSV file with Excel (big mistake) and now i got an null reference error, but prior to that, the count doesn't work: Capture.PNG
    so there is something that is wrong with my CSV file or with the Reader and I cannot figure what. The thing is that the error occurred right after I changed the csv file... I thought I could modify it without any problem.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CSVReader : MonoBehaviour
    6. {
    7.  
    8.     //this is the public list for all other gameObject to use
    9.     public List<Region> regions = new List<Region>();
    10.  
    11.     void Awake()
    12.     {
    13.         //Debug.Log ("Read the CSV file");
    14.         TextAsset DataCSV = Resources.Load<TextAsset> ("DataCSV");
    15.  
    16.         string[] line = DataCSV.text.Split (new char[] { '\n' });
    17.  
    18.         for(int i = 1; i < line.Length-1; i++)
    19.         {
    20.             string[] part = line [i].Split (new char[]{ ';' });
    21.  
    22.             {
    23.                 Region region = new Region ();
    24.                 region.Nom =  part [0];
    25.                 region.Pays = part [1];
    26.                 float.TryParse (part [2], out region.Superficie);
    27.                 float.TryParse (part [3], out region.Population);
    28.                 float.TryParse (part [4], out region.CroissancePopulation);
    29.                 float.TryParse (part [5], out region.PIB);
    30.                 float.TryParse (part [6], out region.CroissancePIB);
    31.                 region.Langue = part [7];
    32.                 region.Religion = part [8];
    33.                 region.color = new Color (0, 0, 0, 1); //set a default color to black
    34.  
    35.                 regions.Add(region);
    36.             }
    37.         }
    38.  
    39.         Debug.Log ("CSVReader Region Count : " + regions.Count);
    40.  
    41.         foreach(Region region in regions)
    42.         {
    43.             Debug.Log ("Nom: " + region.Nom + ", Pays: " + region.Pays + ", Superficie: " + region.Superficie + ", Population: " + region.Population + ", CroisPop: " + region.CroissancePopulation + ", PIB: " + region.PIB + ", CroisPIB: " + region.CroissancePIB + ", Langue: " + region.Langue + ", Religion: " + region.Religion);
    44.             Debug.Log (region.Pays);
    45.  
    46.         }
    47.  
    48.     }
    49. }
    If you can help me, thanks !!
     
  50. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Look what the debug says, and where is it pointing at. Best if you double click.