Mathf.Lerp misses final value
up vote
2
down vote
favorite
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?
unity3d math lerp
add a comment |
up vote
2
down vote
favorite
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?
unity3d math lerp
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
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?
unity3d math lerp
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?
unity3d math lerp
unity3d math lerp
asked Nov 19 at 20:53
tmighty
1,9591057124
1,9591057124
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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).
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 19 at 21:19
Foggzie
7,00212341
7,00212341
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 19 at 21:21
trollingchar
1616
1616
add a comment |
add a comment |
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).
add a comment |
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).
add a comment |
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).
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).
answered Nov 21 at 12:46
Ewout Bos
1
1
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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