Search Unity

Question Find variable by string name

Discussion in 'Scripting' started by Karma_XX, Mar 26, 2023.

  1. Karma_XX

    Karma_XX

    Joined:
    May 12, 2022
    Posts:
    10
    Good afternoon,
    I'm trying to find a way to find a variable under a script by knowing the name.

    Let me explain better;
    Code (CSharp):
    1. if(Mother.name == "Height"){
    2.     Value = Script.Height;
    3. }else if(Mother.name == "Head Size"){
    4.     Value = Script.HeadSize;
    5. }else{
    6.     Value = Script.BodySize;
    7. }
    How could i write this part of the script easier? Cause I believe it will slow all the script down as i'm going to make the "else if" a lot longer. And it will be annoying to adjust or look at the script everytime.

    I was thinking of storing the Mother gameobject name in a string variable, then find the variable under the script by that string value. Idk how tho.

    Thanks a lot.
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    I am pretty sure that one could use reflections to accomplish that, but reflections are such a specific topic that im almost certain that whatever your actual usecase may be can be represented and solved a lot more elegantly. "Specific" as in the average programmer likely wont touch reflections, ever.

    This is highly likely an XY Problem, so please describe your actual usecase and setup and the problem you attempt to address with this solution. We may then be able to give better feedback.
     
  3. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    322
    It sounds like you want a lookup table, getting values by name. You could use a Dictionary, call it lookupTable instead of single variables and access the values by:
    Value = Script.lookupTable.GetValueOrDefault(Mother.name);

    or
    Value = Script.lookupTable[Mother.name];


    You can also check for validity of a name in the table using:
    if (Script.lookupTable.ContainsKey(Mother.name)...


    https://www.dotnetperls.com/dictionary
     
    Karma_XX and Bunny83 like this.
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,527
    If you need an answer directly, as was mentioned, reflection can do it:
    https://learn.microsoft.com/en-us/dotnet/api/system.type.getfield?view=net-7.0

    Code (csharp):
    1. Value = Script.GetType().GetField(Mother.name, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)?.GetValue(Script) ?? default;
    note - this logic assumes all said "variables" are fields, and not necessarily a property or method.

    This also is technically slow since it needs to look up your field for you. So if performance is your concern, reflection isn't necessarily saving you on performance. But in the same respect it's not so slow that it's unusable.

    For example UnityEvent technically uses reflection. Though it often caches the delegate created from reflection so it only has to reflect on initialize. You could technically do the same with my logic above, it's just the logic gets longer.

    ...

    But as was pointed out by Yoreki... this is an XY problem.

    What are you actually trying to do?

    Reflection can be the solution... again, such as in UnityEvent, how else are you going to configure the callback function through the editor? Delegates aren't serializable, so you need to build your delegate at runtime, and that can be accomplished via reflection.

    But does that mean your situation necessarily needs to use reflection?

    I'm already suspect of things like using the name property of some object named "Mother". Like... wtf is even going on here? Is Value a float/int/number? Are all potential fields/variables you're accessing also numbers? What should happen if someone puts in the name of a field/variable that doesn't exist OR is of a type that Value doesn't support (bool? string? Component???)

    What is Value even for?

    I see names like Head Size and Body Size... is this some attempt at a factory pattern? Why not use the factory pattern?
     
  5. Karma_XX

    Karma_XX

    Joined:
    May 12, 2022
    Posts:
    10
    Your method caught my attention.
    I tried looking at the site you sent me, and around google, but i don't really understand how i could use it.
    Mind writing an example?
    Thank you a lot
     
  6. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    322
    Karma_XX likes this.
  7. Karma_XX

    Karma_XX

    Joined:
    May 12, 2022
    Posts:
    10
    The script gives me problems.


    Code (CSharp):
    1. public Dictionary<string, string> FindValue = new Dictionary<string, string>()
    2.     {
    3.         {"Height","Height"},
    4.         {"BodySize","BodySize"},
    5.         {"HeadSize","HeadSize"}
    6.     };
    7.  
    8. public void Start()
    9. {
    10. Value = Script.FindValue[Mother.name];
    11. }
    It says:
    Severity Code Description Project File Row Status of deletion
    Error CS1061 'OcTree' does not contain a definition of 'FindValue' and no accessible extension method 'FindValue' was found that takes a first argument of type 'OcTree'. Probably missing a using directive or assembly reference.
     
  8. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    322
    Remove the "Script."
    Your Dictionary is called "FindValue" and you can access it like a variable. Script. is from your old code and my example.
    Also, I am not sure what Mother.name is. Try this for a start:

    Code (CSharp):
    1. public Dictionary<string, string> FindValue = new Dictionary<string, string>()
    2.     {
    3.         {"Height","1.65cm"},
    4.         {"BodySize","XL"},
    5.         {"HeadSize","56cm"}
    6.     };
    7. public void Start()
    8. {
    9. Value = FindValue["HeadSize"];
    10. }
     
    Karma_XX likes this.
  9. Karma_XX

    Karma_XX

    Joined:
    May 12, 2022
    Posts:
    10
    oh then we were thinking of different things, thanks anyway.