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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

[SOLVED] Dynamic number mapping?

Discussion in 'Scripting' started by GeekStories, Oct 9, 2018.

  1. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    I have 3 floats

    Price (float)
    Quality (float)
    Interest (float)

    Price being 0-100
    Quality being 0-100
    *these are set by the user using a slider

    Interest being also 0-100
    However this is determined by the other 2 variables.

    My problem is I can't manage to make it work. I don't know what mathematical function to use. I've tried using map (from Arduino converted to C#) and it wouldn't work, it would always return a value of the largest negative integer, which is crazy weird. I've tried other methods like Mathf.Clamp(), which worked, but didn't work at the same time, it was sketchy and would break very, very, very easily.

    I don't know how to do this. I've spent around 2 hours trying to figure this out and have had no luck.

    Any help is appreciated.

    Cheers.
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    " My problem is I can't manage to make it work. "

    It seems to me that you would make great progress if you can tell us what 'it' is beside the fact that interest is a function of Price and Quality. Do you have that function? What do you want to simulate? Can you describe in your own words how Price and Quality influence Interest?

    -ch
     
  3. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    Interest is a percentage, its what factors how much sales the user generates. Price and Quality both determine how much interest there is, high price + low quality = low interest or low price + high quality = high interest. The user has to balance all the variables to generate lots of interest and in return more sales. If that made any sense. I'm trying to simulate a super basic 'market' on a very low level.
     
  4. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    You still haven't explained what relationship all the values have.
    From that post, it looks like interest == quality.
    What do you really WANT

    I assume your sliders aready clamp the first 2 values between 0 and 100
     
  5. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    It could be that its 2am as to why I can't explain it, my apologies. I'll try again.

    So..
    price is something the user can set using a slider. Max being 100 and Min being 0 (although it should be 1 now I think about it)

    quality is also something the user can set using a slider. Max being 100 and Min being 0.

    Interest is a value that is determined through factoring both Price and Quality. As with the real life market, if you want to buy a watch or a phone per say, and its bad quality and priced really high then you won't be very interested. Even if it was good quality, yet still very high priced interest wouldn't be as high as if it was cheaper. Yes I could just say interest = quality, but I want price as a factor in the equation.

    Correct, my 2 sliders are clamped between 0 and 100 using Whole Numbers.
     
  6. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
  7. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    I have tried using that. Its the first thing I tried doing, but when I did exactly that and changed it to float all it did was set interest to -2,147,483,648 no matter what changed (price or quality)
     
  8. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    8,998
  9. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    The code works (assuming values are nonzero).
    We still dont know how you want to map values tho
    Code (CSharp):
    1.     float cost, quality, desire;
    2.  
    3.     void OnGUI()
    4.     {
    5.         GUILayout.BeginHorizontal();
    6.         GUILayout.Label("Cost: " + cost, GUILayout.Width(150));
    7.         cost = GUILayout.HorizontalSlider(cost, 0, 100, GUILayout.Width(200));
    8.         GUILayout.EndHorizontal();
    9.  
    10.         GUILayout.BeginHorizontal();
    11.         GUILayout.Label("Quality: " + quality, GUILayout.Width(150));
    12.         quality = GUILayout.HorizontalSlider(quality, 0, 100, GUILayout.Width(200));
    13.         GUILayout.EndHorizontal();
    14.  
    15.         desire = Map(cost, 0, quality, 100, 0);
    16.         GUILayout.Label("Desire: " + desire, GUILayout.Width(200));
    17.     }
    18.  
    19.     float Map(float x, float in_min, float in_max, float out_min, float out_max)
    20.     {
    21.         return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    22.     }
    23.  
     
  10. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    Mkay, so I plugged that in and changed it up and it does the same as the normal Map method converted from Arduino. It works, but for the most part. It still has issues. The issue is once Price is below 50 and Quality is above or at 50, when you lower the price, interest goes down as well.
     
  11. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    When Price is greater than Quality, the map function works great, exactly how I want it to. However when Price drops below Quality, it does still technically work, just backwards. So when price drops and quality increases, interest drops. When it should be the other way around.
     
  12. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Okay, but you still haven't quantified what relationship price and quality actually have on desire.

    I think the real problem is that this isn't some simple linear relationship. Isn't desire always going to be zero when quality is zero, regardless of price? And Desire will be 100% when the thing is free?
    If you fill in this, you might understand
     
  13. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    I see where you're coming from with the whole zero thing.

    Lets make it impossible for Quality or Price to be zero. The lowest they can go is 1.

    This would make it possible to figure out Interest with simple math.

    Take whichever is smaller, divide it by the larger then multiply by 100 to get the interest value, and having it impossible for Price or Quality to be 0, then there isn't any dividing by 0.The smallest possible equation would be (1/1) * 100 which would be %100 interest. But that doesn't make any sense in real life. If something was $1, and had %1 quality (real life alternative could be condition or usefulness or something). Not %100 of people would buy it. And if you change Price or Quality to 2, then it would be (1/2) * 100 which would be %50 interest. A %50 change that just doesn't make any sense for charging an extra dollar or adding an extra 1 percent quality..
     
  14. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Exactly...
    So..... as the person in charge of this, what do you want desire to be when the thing is $1 with 1% quality, or $100 and 100%, or $50 and 50%, etc (you still havent said - I can't provide a formula without KNOWING what result you want)
     
  15. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    After thinking about it, I think the only logical way of doing this is to put a cap on Quality, both min and max, and also ensure Price is always greater than Quality. I can't think of any other way of doing it.

    Otherwise, I want it logical. Not super realistic. Just so it makes sense to any ol' joe.

    $1 and %1 would be 0 interest
    $50 and %50 would likely be 50 interest
    $100 and 100% would be low interest, like say 10 interest

    But when you mix ie

    $44 and %65 would be 67 interest which makes sense
    $23 and %11 would be 47 interest which also makes sense
    $88 and %16 would be 18 interest, but really should be lower, more like between 1-5 interest as it wouldn't make sense
     
  16. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    When you say 'sense' and 'logic' I dunno if thats programmer logic or market shopper logic (definatly different)

    I'm guessing that you want this kind of distribution (you only gave 6 data points from an infinite number of possibilites)
     
    barskey likes this.
  17. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Thats based on the formula desire = quality * (1-cost)
    [This is alot easier when working with values in the 0-1 range]
    When you use exactly desire = quality * (1-cost) you get this distribution, which looks a bit concentrated at the top left corner, so you need to adjust the influences of cost and quality

    Try running the code below and see if you get a distribution you like
    • f1 is kind of like 'How rich are people generally'
    • f2 is kind of like 'How much do people care about quality'
    • f3 is a final step adjustment, sort of like market populairty
    • f4 is 'how willing are people to buy zero quality product' - if this is zero, noone will ever buy zero quality
    • f5 is 'how willing are people to buy maximum price product' - if this is zero, noone will ever pay full price
    Code (CSharp):
    1.     Texture2D blankTex;
    2.     public Gradient colorMap; //change this in inspector, or leave it blank to generate normal heatmap
    3.  
    4.     float f1 = 2f;
    5.     float f2 = 0.5f;
    6.     float f3 = 1;
    7.     float f4 = 0;
    8.     float f5 = 0;
    9.  
    10.     float count = 20; //how many grid cells to show
    11.  
    12.     private void Start()
    13.     {
    14.         if (colorMap.colorKeys[0].color == colorMap.colorKeys[1].color)
    15.         {
    16.             colorMap = new Gradient();
    17.             colorMap.colorKeys = new GradientColorKey[] {
    18.                 new GradientColorKey(Color.blue, 0),
    19.                 new GradientColorKey(Color.cyan, 0.25f),
    20.                 new GradientColorKey(Color.green, 0.5f),
    21.                 new GradientColorKey(Color.yellow, 0.75f),
    22.                 new GradientColorKey(Color.red, 1) };
    23.         }
    24.         blankTex = new Texture2D(1, 1);
    25.         blankTex.SetPixel(0, 0, Color.white);
    26.     }
    27.  
    28.     void OnGUI()
    29.     {
    30.         GUILayout.BeginHorizontal();
    31.         GUILayout.Label("f1: " + f1, GUILayout.Width(100));
    32.         f1 = GUILayout.HorizontalSlider(f1, 0, 10, GUILayout.Width(200));
    33.         GUILayout.EndHorizontal();
    34.  
    35.         GUILayout.BeginHorizontal();
    36.         GUILayout.Label("f2: " + f2, GUILayout.Width(100));
    37.         f2 = GUILayout.HorizontalSlider(f2, 0, 3, GUILayout.Width(200));
    38.         GUILayout.EndHorizontal();
    39.  
    40.         GUILayout.BeginHorizontal();
    41.         GUILayout.Label("f3: " + f3, GUILayout.Width(100));
    42.         f3 = GUILayout.HorizontalSlider(f3, 0, 5, GUILayout.Width(200));
    43.         GUILayout.EndHorizontal();
    44.  
    45.         GUILayout.BeginHorizontal();
    46.         GUILayout.Label("f4: " + f4, GUILayout.Width(100));
    47.         f4 = GUILayout.HorizontalSlider(f4, 0, 0.2f, GUILayout.Width(200));
    48.         GUILayout.EndHorizontal();
    49.  
    50.         GUILayout.BeginHorizontal();
    51.         GUILayout.Label("f5: " + f5, GUILayout.Width(100));
    52.         f5 = GUILayout.HorizontalSlider(f5, 0, 0.2f, GUILayout.Width(200));
    53.         GUILayout.EndHorizontal();
    54.  
    55.         GUI.Label(new Rect(10, 160, 200, 20), "High");
    56.         GUI.Label(new Rect(10, 180, 200, 20), "^");
    57.         GUI.Label(new Rect(10, 200, 200, 20), "Quality");
    58.         GUI.Label(new Rect(10, 220, 200, 20), "V");
    59.         GUI.Label(new Rect(10, 240, 200, 20), "Low");
    60.         GUI.Label(new Rect(200, 110, 200, 20), "Low  <-- Price --> High");
    61.  
    62.         float price, quality, desire;
    63.         for (int p = 0; p < count + 1; p++)
    64.         {
    65.             price = p / count;
    66.             price = price * (1 - f5);
    67.             price = Mathf.Pow(price, f1);
    68.  
    69.             for (int q = 0; q < count + 1; q++)
    70.             {
    71.                 quality = (count - q) / count;
    72.                 quality = quality * (1 - f4) + f4;
    73.                 quality = Mathf.Pow(quality, f2);
    74.  
    75.                 desire = quality * (1 - price);
    76.                 desire = Mathf.Pow(desire, f3); ;
    77.  
    78.                 GUI.color = colorMap.Evaluate(desire);
    79.                 GUI.DrawTexture(new Rect(50 + p * 30, 130 + q * 30, 30, 30), blankTex);
    80.                 GUI.color = Color.black;
    81.                 GUI.Label(new Rect(50 + p * 30, 130 + q * 30, 30, 30), (desire * 100).ToString("00") + "");
    82.             }
    83.         }
    84.     }
    85.  
    If you find good values, then the formula is (if you pass values from 0 to 100)
    Code (CSharp):
    1.     float Interest(float price, float quality)
    2.     {
    3.         price = price / 100f;
    4.         quality = quality / 100f;
    5.         return (Mathf.Pow(Mathf.Pow(quality * (1 - f4) + f4, f2) * (1 - Mathf.Pow(price * (1 - f5), f1)), f3)) * 100f;
    6.     }
     
    GeekStories and barskey like this.
  18. barskey

    barskey

    Joined:
    Nov 19, 2017
    Posts:
    207
    @hpjohn has a great answer.

    Just for further thought... another way to think about this is that you need a series of curves. Since you have 3 values you want to plot on a 2-axis graph, we pick one variable to fix, and then draw a curve relating the other two.

    In this example, take a fixed value of quality. Say it is 1. Then you could graph price on the x-axis and interest on the y. The quality quality would actually be the y-intercept of the slope. If the curves are linear, they would look like this:


    Each curve plots the interest in the Y, price on the X for a given quality. In this example the equation for interest would be
    interest = Mathf.Clamp(quality - m * price, 0f, 1f);
    where m is the slope of the curve.

    Exponential curves would look like this:


    In this example the equation for interest would be
    interest = Mathf.Sqrt(Mathf.Clamp(quality - Mathf.Pow(price, n), 0f, 1f));
    where n is the exponent to stretch the curves.

    So reading the bottom example, the top blue curve is quality = 1. When price is 0, interest is 1. As price increases, interest will start to drop when the price reaches about 0.4, and by the time price is 0.8, interest is also about 0.8. And when price is 1, interest is 0.
     
    Last edited: Oct 9, 2018
  19. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    Your answer worked a lot better than the other attempts, seriously thanks so much. You've been a great help @hpjohn

    So the issue I'm having and has been persistent over all the attempts at getting this working is, when Price is less than Quality, then the interest goes backwards. So instead of interest dropping when the price goes up, it also goes up and when Quality goes up, interest goes down. The two values basically swap places when Price is less than Quality. Otherwise it works great.

    @barskey Thanks for the input, puts another view on how to solve the issue I'm having. I've given your idea a run through and it does work which is great but is has the exact same problem as mentioned with the values doing a flip flop when one is greater than the other.
     
  20. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    After fiddling with the numbers for a bit I got it working perfectly. Just wanna throw a huge thank you to @hpjohn for helping me. It's greatly appreciated :D