Mathf.Lerp misses final value











up vote
2
down vote

favorite
1












I'm using Mathf.Lerp to animate a circular progress bar.



The progress bar is an image that has a property named "FillAmount":



0 means not filled
1 means filled


Along with the Fill property "Radial 360", it acts somewhat like a clock.



For some reason, the final value after executing the Lerp function is missed, and I don't see how I could improve the function to end up with the expected result.



My circular progress bar is a 3/4 ring, that's why I multiply the uFrom and uTo (which are between 0 and 100) by 0.75.



This is my code:



public IEnumerator AnimateHealthChange(int uFrom, int uTo)
{
float fFade = 0.25f;

float fOld = ((uFrom * 0.75f) / 100);
float fNew = ((uTo * 0.75f) / 100);

Debug.Log("Changing from " + fOld.ToString() + " to " + fNew.ToString());

for (float t = 0.01f; t < fFade; t += Time.deltaTime)
{
ImageHealthRing.fillAmount = Mathf.Lerp(fOld, fNew, Mathf.Min(1, t / fFade));
yield return null;//
}

Debug.Log("Final filling after for-next-statement: " + ImageHealthRing.fillAmount.ToString());

yield return null;
}


For example, when I call AnimateHealthChange(0, 100), I get the following log outputs:



Changing from 0 to 0.75

Final filling after for-next-statement: 0.6807814


I expected the final result to 0.75, not 0.6807814.



Does anybody see my mistake, or did I use Lerp incorrectly?



enter image description here










share|improve this question


























    up vote
    2
    down vote

    favorite
    1












    I'm using Mathf.Lerp to animate a circular progress bar.



    The progress bar is an image that has a property named "FillAmount":



    0 means not filled
    1 means filled


    Along with the Fill property "Radial 360", it acts somewhat like a clock.



    For some reason, the final value after executing the Lerp function is missed, and I don't see how I could improve the function to end up with the expected result.



    My circular progress bar is a 3/4 ring, that's why I multiply the uFrom and uTo (which are between 0 and 100) by 0.75.



    This is my code:



    public IEnumerator AnimateHealthChange(int uFrom, int uTo)
    {
    float fFade = 0.25f;

    float fOld = ((uFrom * 0.75f) / 100);
    float fNew = ((uTo * 0.75f) / 100);

    Debug.Log("Changing from " + fOld.ToString() + " to " + fNew.ToString());

    for (float t = 0.01f; t < fFade; t += Time.deltaTime)
    {
    ImageHealthRing.fillAmount = Mathf.Lerp(fOld, fNew, Mathf.Min(1, t / fFade));
    yield return null;//
    }

    Debug.Log("Final filling after for-next-statement: " + ImageHealthRing.fillAmount.ToString());

    yield return null;
    }


    For example, when I call AnimateHealthChange(0, 100), I get the following log outputs:



    Changing from 0 to 0.75

    Final filling after for-next-statement: 0.6807814


    I expected the final result to 0.75, not 0.6807814.



    Does anybody see my mistake, or did I use Lerp incorrectly?



    enter image description here










    share|improve this question
























      up vote
      2
      down vote

      favorite
      1









      up vote
      2
      down vote

      favorite
      1






      1





      I'm using Mathf.Lerp to animate a circular progress bar.



      The progress bar is an image that has a property named "FillAmount":



      0 means not filled
      1 means filled


      Along with the Fill property "Radial 360", it acts somewhat like a clock.



      For some reason, the final value after executing the Lerp function is missed, and I don't see how I could improve the function to end up with the expected result.



      My circular progress bar is a 3/4 ring, that's why I multiply the uFrom and uTo (which are between 0 and 100) by 0.75.



      This is my code:



      public IEnumerator AnimateHealthChange(int uFrom, int uTo)
      {
      float fFade = 0.25f;

      float fOld = ((uFrom * 0.75f) / 100);
      float fNew = ((uTo * 0.75f) / 100);

      Debug.Log("Changing from " + fOld.ToString() + " to " + fNew.ToString());

      for (float t = 0.01f; t < fFade; t += Time.deltaTime)
      {
      ImageHealthRing.fillAmount = Mathf.Lerp(fOld, fNew, Mathf.Min(1, t / fFade));
      yield return null;//
      }

      Debug.Log("Final filling after for-next-statement: " + ImageHealthRing.fillAmount.ToString());

      yield return null;
      }


      For example, when I call AnimateHealthChange(0, 100), I get the following log outputs:



      Changing from 0 to 0.75

      Final filling after for-next-statement: 0.6807814


      I expected the final result to 0.75, not 0.6807814.



      Does anybody see my mistake, or did I use Lerp incorrectly?



      enter image description here










      share|improve this question













      I'm using Mathf.Lerp to animate a circular progress bar.



      The progress bar is an image that has a property named "FillAmount":



      0 means not filled
      1 means filled


      Along with the Fill property "Radial 360", it acts somewhat like a clock.



      For some reason, the final value after executing the Lerp function is missed, and I don't see how I could improve the function to end up with the expected result.



      My circular progress bar is a 3/4 ring, that's why I multiply the uFrom and uTo (which are between 0 and 100) by 0.75.



      This is my code:



      public IEnumerator AnimateHealthChange(int uFrom, int uTo)
      {
      float fFade = 0.25f;

      float fOld = ((uFrom * 0.75f) / 100);
      float fNew = ((uTo * 0.75f) / 100);

      Debug.Log("Changing from " + fOld.ToString() + " to " + fNew.ToString());

      for (float t = 0.01f; t < fFade; t += Time.deltaTime)
      {
      ImageHealthRing.fillAmount = Mathf.Lerp(fOld, fNew, Mathf.Min(1, t / fFade));
      yield return null;//
      }

      Debug.Log("Final filling after for-next-statement: " + ImageHealthRing.fillAmount.ToString());

      yield return null;
      }


      For example, when I call AnimateHealthChange(0, 100), I get the following log outputs:



      Changing from 0 to 0.75

      Final filling after for-next-statement: 0.6807814


      I expected the final result to 0.75, not 0.6807814.



      Does anybody see my mistake, or did I use Lerp incorrectly?



      enter image description here







      unity3d math lerp






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 19 at 20:53









      tmighty

      1,9591057124




      1,9591057124
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          Your for loop is a problem since it makes no guarantees:



          for (float t = 0.01f; t < fFade; t += Time.deltaTime)


          Time.deltaTime can be any number (depending on the performance of the game and the framerate) and you're using t < fFade instead of t <= fFade so even if you do, by chance, end up with t == fFade, (which is the value it should end on to fill properly) it's going to skip that iteration of the loop.



          The easiest solution here would be to just add an extra statement after the loop that forces fillAmount to the proper value:



              ...
          yield return null;//
          }
          ImageHealthRing.fillAmount = fNew;


          This way your loop is still handling the animation and when your function ends, you're guaranteeing that it's ending on the proper value.






          share|improve this answer




























            up vote
            2
            down vote













            Probably it's in for loop. See how it's executed:
            Initially, t is set to 0.01. Healthbar is changed a little.
            Then, t is increased by Time.deltaTime. For example, it happens to be 0.17. Now t equals 0.18 and loop continues to run.



            But when after another increment t becomes greater or equal than fFade, program will exit loop without changing the healthbar. In my example, the last processed number will be 0.18.



            How to solve this? You should set fillAmount to fNew right after the loop.






            share|improve this answer




























              up vote
              0
              down vote













              Instead of using a for loop. Use a while loop. so your code runs until it reaches the desired value.



              Right now you are exiting based on time and not based on the desired result.
              You can still run every frame and animate by time but you should not stop the code based on the time it runs.



              In addition, it might also be worth clamping/setting the value when you exit the loop. Either set it to the parameter you entered in the function( or fNew in your case).






              share|improve this answer





















                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53382475%2fmathf-lerp-misses-final-value%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                2
                down vote



                accepted










                Your for loop is a problem since it makes no guarantees:



                for (float t = 0.01f; t < fFade; t += Time.deltaTime)


                Time.deltaTime can be any number (depending on the performance of the game and the framerate) and you're using t < fFade instead of t <= fFade so even if you do, by chance, end up with t == fFade, (which is the value it should end on to fill properly) it's going to skip that iteration of the loop.



                The easiest solution here would be to just add an extra statement after the loop that forces fillAmount to the proper value:



                    ...
                yield return null;//
                }
                ImageHealthRing.fillAmount = fNew;


                This way your loop is still handling the animation and when your function ends, you're guaranteeing that it's ending on the proper value.






                share|improve this answer

























                  up vote
                  2
                  down vote



                  accepted










                  Your for loop is a problem since it makes no guarantees:



                  for (float t = 0.01f; t < fFade; t += Time.deltaTime)


                  Time.deltaTime can be any number (depending on the performance of the game and the framerate) and you're using t < fFade instead of t <= fFade so even if you do, by chance, end up with t == fFade, (which is the value it should end on to fill properly) it's going to skip that iteration of the loop.



                  The easiest solution here would be to just add an extra statement after the loop that forces fillAmount to the proper value:



                      ...
                  yield return null;//
                  }
                  ImageHealthRing.fillAmount = fNew;


                  This way your loop is still handling the animation and when your function ends, you're guaranteeing that it's ending on the proper value.






                  share|improve this answer























                    up vote
                    2
                    down vote



                    accepted







                    up vote
                    2
                    down vote



                    accepted






                    Your for loop is a problem since it makes no guarantees:



                    for (float t = 0.01f; t < fFade; t += Time.deltaTime)


                    Time.deltaTime can be any number (depending on the performance of the game and the framerate) and you're using t < fFade instead of t <= fFade so even if you do, by chance, end up with t == fFade, (which is the value it should end on to fill properly) it's going to skip that iteration of the loop.



                    The easiest solution here would be to just add an extra statement after the loop that forces fillAmount to the proper value:



                        ...
                    yield return null;//
                    }
                    ImageHealthRing.fillAmount = fNew;


                    This way your loop is still handling the animation and when your function ends, you're guaranteeing that it's ending on the proper value.






                    share|improve this answer












                    Your for loop is a problem since it makes no guarantees:



                    for (float t = 0.01f; t < fFade; t += Time.deltaTime)


                    Time.deltaTime can be any number (depending on the performance of the game and the framerate) and you're using t < fFade instead of t <= fFade so even if you do, by chance, end up with t == fFade, (which is the value it should end on to fill properly) it's going to skip that iteration of the loop.



                    The easiest solution here would be to just add an extra statement after the loop that forces fillAmount to the proper value:



                        ...
                    yield return null;//
                    }
                    ImageHealthRing.fillAmount = fNew;


                    This way your loop is still handling the animation and when your function ends, you're guaranteeing that it's ending on the proper value.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 19 at 21:19









                    Foggzie

                    7,00212341




                    7,00212341
























                        up vote
                        2
                        down vote













                        Probably it's in for loop. See how it's executed:
                        Initially, t is set to 0.01. Healthbar is changed a little.
                        Then, t is increased by Time.deltaTime. For example, it happens to be 0.17. Now t equals 0.18 and loop continues to run.



                        But when after another increment t becomes greater or equal than fFade, program will exit loop without changing the healthbar. In my example, the last processed number will be 0.18.



                        How to solve this? You should set fillAmount to fNew right after the loop.






                        share|improve this answer

























                          up vote
                          2
                          down vote













                          Probably it's in for loop. See how it's executed:
                          Initially, t is set to 0.01. Healthbar is changed a little.
                          Then, t is increased by Time.deltaTime. For example, it happens to be 0.17. Now t equals 0.18 and loop continues to run.



                          But when after another increment t becomes greater or equal than fFade, program will exit loop without changing the healthbar. In my example, the last processed number will be 0.18.



                          How to solve this? You should set fillAmount to fNew right after the loop.






                          share|improve this answer























                            up vote
                            2
                            down vote










                            up vote
                            2
                            down vote









                            Probably it's in for loop. See how it's executed:
                            Initially, t is set to 0.01. Healthbar is changed a little.
                            Then, t is increased by Time.deltaTime. For example, it happens to be 0.17. Now t equals 0.18 and loop continues to run.



                            But when after another increment t becomes greater or equal than fFade, program will exit loop without changing the healthbar. In my example, the last processed number will be 0.18.



                            How to solve this? You should set fillAmount to fNew right after the loop.






                            share|improve this answer












                            Probably it's in for loop. See how it's executed:
                            Initially, t is set to 0.01. Healthbar is changed a little.
                            Then, t is increased by Time.deltaTime. For example, it happens to be 0.17. Now t equals 0.18 and loop continues to run.



                            But when after another increment t becomes greater or equal than fFade, program will exit loop without changing the healthbar. In my example, the last processed number will be 0.18.



                            How to solve this? You should set fillAmount to fNew right after the loop.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 19 at 21:21









                            trollingchar

                            1616




                            1616






















                                up vote
                                0
                                down vote













                                Instead of using a for loop. Use a while loop. so your code runs until it reaches the desired value.



                                Right now you are exiting based on time and not based on the desired result.
                                You can still run every frame and animate by time but you should not stop the code based on the time it runs.



                                In addition, it might also be worth clamping/setting the value when you exit the loop. Either set it to the parameter you entered in the function( or fNew in your case).






                                share|improve this answer

























                                  up vote
                                  0
                                  down vote













                                  Instead of using a for loop. Use a while loop. so your code runs until it reaches the desired value.



                                  Right now you are exiting based on time and not based on the desired result.
                                  You can still run every frame and animate by time but you should not stop the code based on the time it runs.



                                  In addition, it might also be worth clamping/setting the value when you exit the loop. Either set it to the parameter you entered in the function( or fNew in your case).






                                  share|improve this answer























                                    up vote
                                    0
                                    down vote










                                    up vote
                                    0
                                    down vote









                                    Instead of using a for loop. Use a while loop. so your code runs until it reaches the desired value.



                                    Right now you are exiting based on time and not based on the desired result.
                                    You can still run every frame and animate by time but you should not stop the code based on the time it runs.



                                    In addition, it might also be worth clamping/setting the value when you exit the loop. Either set it to the parameter you entered in the function( or fNew in your case).






                                    share|improve this answer












                                    Instead of using a for loop. Use a while loop. so your code runs until it reaches the desired value.



                                    Right now you are exiting based on time and not based on the desired result.
                                    You can still run every frame and animate by time but you should not stop the code based on the time it runs.



                                    In addition, it might also be worth clamping/setting the value when you exit the loop. Either set it to the parameter you entered in the function( or fNew in your case).







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Nov 21 at 12:46









                                    Ewout Bos

                                    1




                                    1






























                                        draft saved

                                        draft discarded




















































                                        Thanks for contributing an answer to Stack Overflow!


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid



                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.


                                        To learn more, see our tips on writing great answers.





                                        Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                        Please pay close attention to the following guidance:


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid



                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.


                                        To learn more, see our tips on writing great answers.




                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function () {
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53382475%2fmathf-lerp-misses-final-value%23new-answer', 'question_page');
                                        }
                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown







                                        Popular posts from this blog

                                        "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                                        Alcedinidae

                                        Origin of the phrase “under your belt”?