Change one value gradually to another over set period of time

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By eyeEmotion

Ok, I’m beginning to notice that all my lerps are wrong and actually don’t work like they should (over a set period of time). And I don’t find a straight answer.
So in my current problem, I have a variable scale_looking, which changes depending on how fast the car is driving. So lets say it’s 30. This is the amount I want my camera to rotate (either left or right) from looking straight. And I want this over a period of time, let’s say 3 seconds (also need it go back).
I thought lerp would to this… but lerp just gives a value back only once, if I now understand correctly. So how do I actually set things up so that I have a startvalue (ex. 0), and endvalue (ex. 30) and have it gradually change from start to end over time (ex. 3 sec.

Currently I have this working, but the change is abrupt:

func get_input(delta):
	look_around = Input.get_action_strength("turn_left") - Input.get_action_strength("turn_right")
	var scale_looking = follow_this.fwd_mpsf / 3
	if (look_around < -0.95 or look_around > 0.95):
		rotate_object_local(Vector3.UP, lerp(0, scale_looking * look_around, delta))

Here is the current effect:

So I’m aware I’m doing it wrong, but since I’m going to need it several times more, I want to know how it is approached the right way.


:bust_in_silhouette: Reply From: Trollend

It sounds like you want to Tween. A tween gradually changes the values or properties of a node over a set period of time.

See specifically the interpolate method of tween: Tween — Godot Engine (3.2) documentation in English.

In my experience, they can be a little bit difficult to use, but with enough testing and experimentation, all the methods are there to do what you would like to. It sounds like you possibly need to get some value back as well. The tween won’t do this but you can always check the properties of the node you are tweening at each time step.

Oh ok, thanks. I’ll look into that then. But am I still able to use that rotate_object_local? Because that was the key to even get my camera looking to the left or right. And Tweening requires a Tween node to work, as I seem to read?
Everywhere I look, they seem to use lerp for everything going from one value to another.

I constantly keep going in the wrong direction. The docs say what things are, but mostly not how, when and where to use them. Certainly confusing for beginners.

eyeEmotion | 2020-04-27 04:35

I’m not sure about lerp, I mostly do 2D development in Godot, 3D isn’t my strong suit. If you want to gradually change a single property of something over a set period of time, that’s tweening. The way you’re doing it doesn’t look wrong to me, but you say it’s abrupt or jerky?

Trollend | 2020-04-27 05:51

It’s abrupt, it doesn’t transition, as seen in the video.
Because the how much it rotates is dependant on the speed, you don’t notice it on low speeds, because jumping from 0 to 5° angle isn’t that noticeable. But at higher speed, the angle could be 30°. So it “jumps” from 0 to 30°, because there is no transition.
I found a simple tutorial about the Tween to understand it a bit better, so that is why I wondered if the rotate_object_local() would still work, given the parameters it needs.

*I also already noticed that I have to constrain it when it should happen. And that this effect should only be applied when

  1. using the joystick at max (that’s why I did if (look_around < -0.95 or look_around > 0.95):(currently even set it to 0.98) , and
  2. only if it’s held more than 2 seconds or so, because I don’t want to have it kick in everytime you hold your joystick to the max. I think any turn you keep holding your joystick at max for more than 2 seconds is a “hard” turn.
    Because a keyboard input always is 0 or 1, I can’t have this effect be used for people that use a keyboard (I think). So I thought I would check if the input comes from the keyboard or from a controller: if (!InputEventKey): . But apparantly a joystick input also seem to be an InputEventKey*

eyeEmotion | 2020-04-27 16:09

Ah, I see the abruptness now. When you turn the car past a degree and the camera rotation kicks in, it’s all at once. I missed that in the video the first time I watched it, sorry about that. I think what you want is still interpolation then, but possibly smoothing interpolation rather than tweening interpolation.

Try this instead of lerp in your rotate object local function. Here is an example from the docs. There’s some good explanation of interpolation there too.

Trollend | 2020-04-27 18:50

Problem is that at the moment I don’t even know how to. To what property/variable.
My “scale_looking” is the end-value. My start value is ??? I would say 0 but then again, if the camera also needs to back… And I would say “look_around” as the float, since that’s always a value between 0 and 1 (or rather -1 and 1 [left-right]). But since object_rotate_local is set behind a condition of my look_around needing to be above 0.99, that would make look_around in the linear_interpolate “1”. But wouldn’t that make it jump again from one to the other? Or is it “delta * look_around”?

Currently I’m trying stuff I have in the form of ( ??? = try variable/property here)

rotate_object_local(Vector3.UP, ???.linear_interpolate(scale_looking, ??look_around??))

The problem is that I can’t see how (and I’m a visual learner). I understand what it says, but most of the time I just don’t know how to apply it to my code. Which object/variable/property goes where.
Most of time things “connect” with me once I applied them, because I then see what is happening. That’s why I started my project, learning by doing.

I get mostly stuck because I’m not used to the syntax yet and not knowing what information comes from the engine. No problems with the variables of my own, since I know why I created them.

eyeEmotion | 2020-04-27 19:42