#Making player move in 2D using Lerp
1 messages · Page 1 of 1 (latest)
might wanna formalize your question in one paragraph
I want it such that if the player holds down a key, a speed value is lerped until it hits a max speed, and holds that same speed until the key is let go, after which it lerps back to it's previous value (before the keypress)
here's my code so far (broken)
float targetFloat = keyPressed ? 1f : 0f;
myFloat = Mathf.Lerp(myFloat, targetFloat, Time.deltaTime * lerpSpeed);
or MoveTowards or whatever smoothing/lerping you want
This way it will never reach the target float though.
and how exactly do i control lerpspeed
i would like it so that it lerps from start to finish in around 0.5 seconds
There's no such thing as lerp speed. Lerp is a function that returns a value based on the parameters you give it.
right then is there a way i can use time.deltaTime inside the lerp and a timer of sorts
i attempted that on my script but couldn't figure out how to put it inside the lerp function
Lerp returns value between A and B based on time t within ranges of 0 to 1. So if you want it to lerp in .5 sec, then increment the t from 0 to 1 in .5 sec.
private float transition;
[SerializeField] private float transitionSpeed = 10f;
[SerializeField] private float minValue = 3f, maxValue = 5f;
public float myFloat;
void UpdateMyFloat()
{
// Transition value moves between 0..1 depending on key press state
float transitionTarget = keyPressed ? 1f : 0f;
transition = Mathf.MoveTowards(transition, transitionTarget, Time.deltaTime * transitionSpeed);
// Update myFloat to be between min and max value, in range of transition
myFloat = Mathf.Lerp(minValue, maxValue, transition);
}
where is the myFloat used in the script?
t += delta time / desiredLerpTime;
and t goes inside the lerp, right?
Basically what Osmal shared.
i'll try to implement it
wait
does Mathf.MoveTowards work like lerp but uses time values?
None of them have to use time values. They are just functions that take input and return a value.
They just do simple math, like x = a + b.
You can use time in your calculations, but that's not gonna change the fact that they just do simple math every frame
myFloat would be your result (green line in your drawing)
okay i understood the script i think
can i just say it from what i understood just to make sure
transition = Mathf.MoveTowards(transition, transitionTarget, Time.deltaTime * transitionSpeed);
this line is instantanouesly set to 0 if button not pressed, or slowlys goes to 1 (but never reaches it(??)) if the button is pressed
I updated the snippet a bit so its easier to tell whats local vars and whats member vars
it moves the transition float over time. It moves it towards 0 if no key is pressed, and 1 if key is pressed.
and it does reach the target value yes
then we use transition to "sample" a value between minValue and maxValue
(with Mathf.Lerp)
does it move at a rate of 0.01
like if I'm running at 60fps then time.deltaTime ~ 0.01 right
are you talking about the MoveTowards line?
yes
if you use Time.deltaTime as t in MoveTowards, it will take 1 second to reach the value
if you use Time.deltaTime * 10, it will take 0.1 seconds
(1 / 10)
does it make sense?
also this is all called from Update
yeah i got that
last question
if i had used a constant, say 0.5 value in t
for Lerp()
does that mean all I would get is just the halfway point between 0 and 10 (if they there a and b in lerp)
and that's why t needs to change?
yes, Mathf.Lerp(0f, 10f, 0.5f) returns 5f
check these
oh ffs the bot keeps removing my message lol
anyway look at Mathf.MoveTowards and Mathf.Lerp in docs
lol
(Vector3/Vector2 also have similiar functions)
i did try to look at them but it's my fault cause i did kinda skim them
so basically both of them are just another way of writing a function f(x) where x is t, and f returns the value x% towards b from a
they are functions, with differing functionality
although they can be used for similiar use case
i see
no, MoveTowards takes a distance instead of t
wait i'm lost again
OH
yeah that's what i wanted to ask
if i used something like Mathf.Smoothstep(0,1,t)
Mathf.MoveTowards(0f, 10f, 3f) returns 3f
for the transitionTime that goes in Lerp
Mathf.MoveTowards(3f, 10f, 3f) returns 6f
one last question
yeah thats a good idea
does Time.deltaTime say more or less the same
because isn't it calculating the value time between current and last frame
yes, but different frames can take different amount of time to process
ideally, your FPS would stay as stable as possible
okay with like a stable 60fps Time.deltaTime returns 1/60
Yes. Although it's different every frame due to many factors. And if you ignore that difference, it will accumulate and break something.
so how did u use it in MoveTowards?
because if it's more or less constant, wouldn't movetowards return the same value every time
Roughly. It will never be exactly 1/60 unless the stars align.
OH
u like
what's the word
REASSIGNED IT
OHHHHHH
so like
first time if u had x = mathf.movetowards(0,1,Time.dtime)
x = 0.1 for first frame
x = 0.2 for second
and so on right?
nah you would do x = Mathf.MoveTowards(x, 1, Time.deltaTime)
notice x as first argument
oh yeah mb
that's what i meant
but for smoothstep, i can't do that, since t is a percent
so does that mean i need an inbuilt timer?
you could change this:
myFloat = Mathf.Lerp(minValue, maxValue, transition);
to this:
myFloat = Mathf.Lerp(minValue, maxValue, Mathf.SmoothStep(0f, 1f, transition));
so that you sample with a smoothed t, not linear
otherwise, smoothstep doesnt really help here
oh even smarter
from now one Mathf.Movetowards is my bae
going to use it instead of timers
yeah i tried to
by drawing lines on my pencil
it did not work out
okay here's my code
float hAxis = Input.GetAxis("Horizontal");
float transitionTarget = hAxis != 0 ? 1f : 0f;
float targetSpeed = hAxis != 0 ? 10f : 0f;
float transitionTime = 0;
transitionTime = Mathf.MoveTowards(transitionTime,transitionTarget,Time.deltaTime);
moveSpeed = Mathf.LerpUnclamped(moveSpeed, targetSpeed,Mathf.SmoothStep(0,1,transitionTime));
return moveSpeed;
so moveSpeed does increase, but letting of the button doesn't seem to bring it back
any idea why?
try Input.GetAxisRaw
instead of getaxis
reason: GetAxis has some smoothing in it, and may never reach 0
alternatively you can replace hAxis != 0 with Mathf.Abs(hAxis) > 0.001f or something
anyway i got some stuff to do
paste code in a paste site or something
no the only thing i want to do now is
make it so that all this happens over the course of 3 seconds, instead of the default 1
divide Time.deltaTime by the amount of seconds
yeah but then
can you stop typing vertically please?
oh yeah sorry my bad.
the lerp is controlled by the transition though
so transition length determines lerp length
okay that makes sense.
if i'm correct, to should take 1/Time.deltaTime * some var frames to finish the transition correct
you can have a float transitionDuration and then do
transitionTime = Mathf.MoveTowards(transitionTime, transitionTarget, Time.deltaTime / transitionDuration);
(i just added the / transitionDuration part to your code)
wait it's that simple?
i don't know whether to cry or rage or be happy
okay it didn't work
yes the movetowards functions takes x seconds to reach one, but the lerp function hits the max value much much faster
would be cool if you show the code 🤷♂️
// Transition value moves between 0..1 depending on key press state
float transitionTarget = hAxis ? 1f : 0f;
float targetSpeed = hAxis ? 10f : 0f;
transitionTime = Mathf.MoveTowards(transitionTime,transitionTarget,Time.deltaTime / accelerationTime);
if (transitionTime > 0 && transitionTime < 0.99f) {
timer += Time.deltaTime;
}
// Update myFloat to be between min and max value, in range of transition
moveSpeed = Mathf.LerpUnclamped(moveSpeed, targetSpeed,transitionTime);
return moveSpeed;
wait no.
this is wrong
moveSpeed = Mathf.LerpUnclamped(moveSpeed, targetSpeed,transitionTime);
and not like in my example
oh
the idea was
moveSpeed = Mathf.LerpUnclamped(minMoveSpeed, maxMoveSpeed, transitionTime);
but then how can i do it so that if the player was already moving at a speed it accelerates/decceleatres
thats nothing like what you originally described..
you wanted a switch that transitions from 0 to 1
or from x to y
i kinda wanted it to go from x to y, then back to x
depending on whether the key is pressed
did you try this?
before saying it doesnt work
lol...
-asks for help
-gets solution
-implements solution wrong
-doesnt correct the solution
-blames solution
it goes from 2 to 10
then 0 to 2
okay that's a fair critique sorry for acting like the toxic noob
maybe i should just give up for now
work on another part
sorry for wasting your time
@dire veldt just tested this and it does work
float transitionTime;
float moveSpeed;
float minSpeed = 2f,
maxSpeed = 10f,
accelerationTime = 2f;
void Test()
{
bool hAxis = Input.GetKey(KeyCode.A);
float transitionTarget = hAxis ? 1f : 0f;
transitionTime = Mathf.MoveTowards(transitionTime, transitionTarget, Time.deltaTime / accelerationTime);
moveSpeed = Mathf.LerpUnclamped(minSpeed, maxSpeed, transitionTime);
print("Speed: " + moveSpeed);
}
private void Update()
{
Test();
}
:O
it moves from 2 to 10 in 2 seconds, and back when you release
I currently have to do something but I'll try it later
If it does work thank you so much
yeah I just wanted to check that nothing is wrong with what i gave you
but you should add just that to an object, then work your way up there, see where it breaks for you
Ive been dev for ages, Unity programming just a few years tho
not an expert but passionate hobbyist
Well I have to go now but again tysm
hey @fringe igloo
if ur not busy
I finally made my 100% own script for the walk cycle
the player moves at a constant rate towards the max speed, while the button is being pressed
i'm proud of it :)
void RunAndWalk() {
bool isMoving = hAxis != 0;
float accelerationRate = (maxSpeed * Time.deltaTime)/timeToMaxSpeed;
print(isMoving);
if (isMoving) {
playerSpeed = Mathf.MoveTowards(playerSpeed, maxSpeed * Mathf.Sign(hAxis), accelerationRate);
} else if (playerSpeed != 0) {
playerSpeed -= Mathf.MoveTowards(0,playerSpeed,accelerationRate);
}