Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Loading values from .ini

Discussion in 'Scripting' started by Aldebaraan, Jun 24, 2020.

  1. Aldebaraan

    Aldebaraan

    Joined:
    Jun 21, 2020
    Posts:
    6
    Two issues:

    #1. I'm trying to make my dll load values from a .ini file. They are going to be used to randomly generate a slider value that will be applied to a character.

    Here's some code:


    Code (CSharp):
    1.  
    2.        int slider = 0;
    3.        string keymin;
    4.        string keymax;
    5.      
    6.        while (slider <= 31) //31 is number of sliders (shapeValueBody[])
    7.         {
    8.          //GetFloat is the function that gets the value from a section/key
    9.           female.customInfo.shapeValueBody[slider] = UnityEngine.Random.Range(GetFloat(FacePreset1, keymin, 0.5f, false), GetFloat(FacePreset1, keymax, 0.8f, false));
    10.           slider++;
    11.         }
    12.  
    13.  
    14.         public static float GetFloat(string section, string name, float defaultValue = 0f, bool autoSave = false)
    15.         {
    16.             float value;
    17.             if (float.TryParse(Instance.IniReadValue(section, name), out value))
    18.                 return value;
    19.             else if (autoSave)
    20.                 SetFloat(section, name, defaultValue);
    21.  
    22.             return defaultValue;
    23.         }
    24.  

    Ini file snippet:

    [FacePreset1]
    Overall_Face_Breadth = 0.35, 0.45 ; this is shapeValueBody[0]. 0.35 is the minimum and 0.45 is the max for the range.
    Upper_face_depth = 0.3, 0.45 ;
    Face_height = 0.4, 0.52 ;
    Lower_face_depth = 0.45, 0.6 ;
    Lower_face_width = 0.1, 0.4 ;



    How do i make the while loop take the first key (Overall_Face_Breadth) min/max values (0.35, 0.45), apply them to keymin and keymax respectively and then proceed to the next key (Upper_face_depth) and do the same until the end of the loop?




    #2. Make the code pick a random preset from a list
    Ini snippet:
    [Presets]
    facepresets = FacePreset1, FacePreset2, FacePreset3


    some code:
    Code (CSharp):
    1. string randompreset = "null";
    2. female.customInfo.shapeValueBody[slider] = UnityEngine.Random.Range(GetFloat(randompreset, keymin, 0.5f, false), UnityEngine.Random.Range(GetFloat(randompreset, keymax, 0.8f, false));
    3.  
    4.  
    5.         public static string GetString(string section, string name, string defaultValue = "", bool autoSave = false)
    6.         {
    7.             string value = Instance.IniReadValue(section, name);
    8.             if (value != "")
    9.                 return value;
    10.             else if (autoSave)
    11.                 SetString(section, name, defaultValue);
    12.  
    13.             return defaultValue;
    14.         }
    15.  
    16.  
    17.  
     
    Last edited: Jun 24, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    I highly recommend switching to JSON for your data storage. INI is a bit antiquated and I'm not even sure what level of native support you could find for it. Even if all your data is already in INI form, I recommend converting it to JSON and using that.

    The most flexible JSON package is the JSON .NET package on the asset store for free.

    As for random, picking from a list just involves getting the items into that list or array first (JSON would handle this as you read your data blob), then picking a number from 0 to the list length. Since Random.Range() is not inclusive on the end when given integer arguments, it looks like:

    Code (csharp):
    1. string[] names = new string [] { "tom", "dick", "harry"};
    2.  
    3. int which = Random.Range( 0, names.Length);
    4.  
    5. Debug.Log( "which = " + which);
    6.  
    7. string theNameIChose = names[which];
    8.  
    9. Debug.Log( "nameChosen = " + theNameIChose);
     
    Aldebaraan and lordofduct like this.
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,385
    Agreed, ini is outdated. Use something like json instead.

    Though looking over your code... you already have code for reading ini via this 'Instance.ReadIniValue'... are you per chance using this stack overflow code to read from ini files? (I found it by just googling 'ReadIniValue' as you did not explain where that method came from and it's not a Unity method):
    https://stackoverflow.com/questions/24096272/inireadvalue-method-returns-empty-string

    Because if so... just so you know that code relies on kernel32 and is Windows specific.

    Next is that your question honestly has nothing to do with ini files. I mean sure you're reading in values from an ini file... but you already have code that does that.

    What you seem to be having a problem with is taking the resulting string and parsing out the information you want from it.

    In this case you're getting back the string: "0.35, 0.45" for the key "Overall_Face_Breadth".

    Well, you got break that string up into its floats. Using something like the String.Split method if you want to do that:
    https://docs.microsoft.com/en-us/dotnet/api/system.string.split?view=netcore-3.1

    Then parse the floats with float.TryParse like your clearly familiar with since you have code that does that.

    ...

    Of course I'm saying this with assumptions of how your ini parsing code works... I have no idea what ACTUALLY comes back. You did not tell us what that code is, how it behaves, where you got it or anything. So assumptions are all around.

    ...

    And in the end, I will repeat that I agree with Kurt-Dekker... use a more modern format that has better modern support. JSON is pretty awesome.

    You ini snippet could be written as:
    Code (csharp):
    1.  
    2. {
    3.     "FacePreset1" : {
    4.         "Overall_Face_Breadth":{ "x":0.35, "y":0.45 },
    5.         "Upper_face_depth":{ "x":0.3, "y":0.45" },
    6.        "Face_height":{ "x":0.4, "y":0.52 },
    7.        "Lower_face_depth":{ "x":0.45, "y":0.6 },
    8.        "Lower_face_width":{ "x":0.1, "y":0.4 }
    9.    }
    10. }
    11.  
    And then in C# you'd create your data contracts as:
    Code (csharp):
    1.  
    2. [System.Serializeable]
    3. public class Token
    4. {
    5.     public FacePreset FacePreset1;
    6. }
    7.  
    8. [System.Serializeable]
    9. public class FacePreset
    10. {
    11.     public Vector2 Overall_Face_Breadth;
    12.     public Vector2 Upper_face_depth;
    13.     public Vector2 Face_height;
    14.     public Vector2 Lower_face_depth;
    15.     public Vector2 Lower_face_width;
    16. }
    17.  
    Then just load it in as:
    Code (csharp):
    1. var token = JsonUtility.FromJson<Token>(System.IO.File.ReadAllText(PATH_TO_JSON));
    2. Vector2 faceBreadth = token.FacePreset1.Overall_Face_Breadth;
    3. //do whatever you want with it
     
    Aldebaraan and Kurt-Dekker like this.
  4. Aldebaraan

    Aldebaraan

    Joined:
    Jun 21, 2020
    Posts:
    6
    Thanks for all the info.

    But about question #2: I want to be able to add more presets without needing to compile.
    e.g.
    {
    "Presets": {
    "bodypresets": ["BodyPreset1, BodyPreset2, BodyPreset3"],
    "facepresets": ["FacePreset1, FacePreset2, FacePreset3"]
    }
    }

    And then pick a random one using Random.Range. Is that possible?
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    JSON data can be baked into your binary (requires at least re-signing your app) or come from an alternative source (internet, file, etc.)

    NOTE: the above bodypresets and/or facepresets are each a 1-entry array of a single string, which I don't think you intend. If there are three separate strings in the array (square brackets are array), then each string has to be in its own quotes, separated by commas.
     
    Aldebaraan likes this.