- Home /
How to increase an int (or float) smoothly over time? (Mathf.Lerp?)
Hi, I've got a question involving increasing a value smoothly over time.
I have a spaceship that fires its thrusters while holding down the mouse key. I would like a speed value displayed that smoothly increases as the mouse key is pressed, and smoothly decreases when released. I am adding code to an existing script. I'm pretty sure I'm using Mathf.Lerp incorrectly. Would anyone be able to help? Thank you.
void Update () {
int speed = 0;
// Start all thrusters when pressing Fire 1
if (Input.GetButtonDown("Fire1")) {
foreach (SU_Thruster _thruster in thrusters) {
_thruster.StartThruster();
speed += (int) Mathf.Lerp (0, 1000, Time.deltaTime);
speedText.text = speed.ToString ();
}
}
// Stop all thrusters when releasing Fire 1
if (Input.GetButtonUp("Fire1")) {
foreach (SU_Thruster _thruster in thrusters) {
_thruster.StopThruster();
speed -= (int) Mathf.Lerp (0, 1000, Time.deltaTime);
speedText.text = speed.ToString ();
}
}
}
Answer by _Gkxd · Apr 14, 2015 at 11:07 PM
You're probably not using Mathf.Lerp
correctly.
If 0 < c < 1
, Mathf.Lerp(a,b,c)
returns a*(1-c)+b*c
.
If c > 1
, the lerp returns b
. If c < 0
, the lerp returns a.
Your actual problem is that the code you have will only be executed when you press down the key and when you let go of the key. It won't run when you're holding down the key. What you want instead is Input.GetKey.
So something that you could do is (pseudocode):
void Update() {
if (Input.GetKey(SOMEKEY)) {
speed += 10 * Time.deltaTime; // Cap at some max value too
}
else {
speed -= 10 * Time.deltaTime; // Cap at some min value too
}
}
(There's no need to use lerp.)
I found a couple of issues with your suggestion, namely that I should be using Input.Get$$anonymous$$ouseButton(0) and Time.time ins$$anonymous$$d of deltaTime. Nevertheless, your post led me in the right direction and it'll work with a little tweaking. Thank you.
I find it strange that you would want Time.time
ins$$anonymous$$d of Time.deltaTime
.
Time.time
is the current time of the game in seconds, so the longer your game has been running, the more will be added to the speed. When you add 0.1*Time.time
to speed, if your game has been running for 100 seconds, each update will add 10 to speed. If your game has been running for 200 seconds, each update will add 20 to your speed.
Time.deltaTime
is the time in between frames in seconds. If your game runs at 60 FPS, then Time.deltaTime
is around 1/60. The reason you want to multiply Time.deltaTime
is so that your speed is independent of framerate. That is, if someone on a laggy computer is running at 10 FPS, you want to add a higher amount to speed to compensate for the lag.
Of course, since Time.deltaTime
is around 1/60, a increment of 0.1 * Time.deltaTime
would actually only increase the speed by around 0.00166, which is probably the "problem." (I'm guessing that the problem was that the speed didn't appear to be changing changing.) Changing the lines to speed += 10 * Time.deltaTime;
will fix this issue. I will change this in my answer. I know for sure that you don't want to multiply Time.time
to what you add on to speed.
As for Input.Get$$anonymous$$ouseButton(0)
, I assumed that you were going for key presses ins$$anonymous$$d of clicks (but both work).
Thank you again for responding. I had figured out why you didn't suggest Time.time right before you posted. :) However, with 100 * Time.deltaTime, my speed value seems to be capping out at around 2-3. Here's the new code:
float speed = 0;
if (Input.Get$$anonymous$$ouseButton (0)) {
speed += 100 * Time.deltaTime; // no maximum
} else {
speed -= 10 * Time.deltaTime; // $$anonymous$$imum 0
}
if (speed <= 0) {
speed = 0;
}
Debug.Log (speed.ToString ("F2"));
speedText.text = speed.ToString("F2");
Either way, you appear to be resetting speed to 0 every frame before tweaking it.
You set it to 0, then add an amount relative to your framerate. If you're managing 60 frames per second, Time.deltaTime = 1/60. Therefore, multiply that by 100 and your speed variable will generally be 100/60 or 1.666666.
This also suggests that you wouldn't be able to slow down, because you're always setting speed to 0 if it's less than 0. If speed is set to 0 before changing it, you subtract from it and turn it negative, then zero it out again, it'll just be zero.
There may be context that's not apparent in the script you're showing us, but that's the best I can make of what I can see.
Answer by LiefLayer · Apr 14, 2018 at 04:22 PM
Ok I wrote this for future readers, this is my own solution to this problem if you need a cap with this your float variable will go from 0 to 1 and you will be able to decide "how fast" (you just need to change 5 with any number):
movementFB2 = movementFB2 < 1f ? movementFB2 + Mathf.Lerp(0, 1, Time.deltaTime * 5) : 1f;
(this is assuming you are using Input.GetKey in an Update, also you will need to put a 0f movementFB2 if you are not using that input).
Answer by shadowpuppet · Mar 01, 2017 at 02:39 PM
I get errors when trying this. Namely saying I cannot convert "float" into "int". I am trying this script with a player health replenish. Rather than having to pick up a health power up I want the player to gradually heal himself. My health scripts for health.currentHealth are all in "int". I mean several scripts would have to be changed on several enemies that inflict damage. So how can I slowly increase an "int" over time?
You have to cast the value into a value type it likes. (100 * Time.deltaTime) will produce a float so if speed is an int try something like:
speed += (int)(100 * Time.deltaTime);