#does that require deltatime
1 messages · Page 1 of 1 (latest)
Right. You are accelerating the character, changing its velocity by a little bit each frame.
The change in velocity depends on how long each frame takes
You could take this even further: the acceleration could change by a little bit every frame
the change in acceleration is "jerk"
but that doesn't really come up a lot...
this makes sense but I'm also multiplying by deltaTime when I change the position in the Move(), but because that's changing position it doesn't matter here..?
how the hell did anyone figure this out
i guess i'll see if things work and if they don't i'll add deltatime to whatever i just added
velocity and position changing are two separate things
velocity is the distance you travel during one second
So for a velocity of 10m/s you'll travel 100 meters in 10 seconds, you multiply the velocity by the time elapsed
You aren't multiplying twice
So when you have your velocity in game, you still have to multiply it by deltaTime to get how much you travelled in that 0.001 seconds
The change in velocity is multiplied by deltaTime, as is the change in position
Vector3 acceleration = Vector3.down;
Vector3 velocity = Vector3.zero;
Vector3 position = Vector3.zero;
void Update() {
velocity += Time.deltaTime * acceleration;
position += Time.deltaTime * velocity;
}
velocity is only multiplied by deltaTime once here: when we use it to adjust position
The change in velocity is certainly based on deltaTime
but if velocity was [0, -10] before the update and we were running at 100 fps, it'd be [0, -10.01] after the update
not [0, -0.1] or something
so if you add something to your velocity that's multiplied by deltatime that's fine
but if you multiply your velocity by deltatime more than once that's bad..?
idk this just doesn't click at all
yes. think about the units here.
acceleration: distance / time / time
velocity: distance / time
position: distance
velocity + acceleration * time
that is OK
the units are compatible
position + velocity * time
that's also OK
position + velocity * time * time
this is bogus
the left side is distance
the right side is...distance * time
meter-seconds
that's a nonsense unit
how do I know if the units are compatible?
they have to be the same
if you multiply velocity by time once, that's distance / time * time
after cancellation, you get distance
thus, this is reasonable to add to your position
if you multiply acceleration by time once, that's distance / time / time * time. After cancellation, that's distance / time.
This is a velocity.
So it's reasonable to add to your velocity
If you multiply velocity by time twice, that's distance / time * time * time, which is distance * time.
I don't have any physical intuition for that one.
i'm having a hard time understanding the way my units work
but i'll probably just experiment until i get something that feels alright
as i have no real education in physics i'll just Guess
you don't need an elaborate education
you just need to count
acceleration * time = velocity
velocity * time = distance
make sure you're only ever adding two of the same thing together.
wdym two of the same thing
By knowing what is what. Basically you don't want to add something like mass to a direction vector, same with this, you wouldn't add time to position or acceleration to velocity. I think they teach such stuff at school in physics class when you're around 17-18 or younger, idk how your education system works
two of the same concept
It's basically algebra. Just balancing an equation
in general, you should only ever add two things if their units match
two amounts of money, two durations, two weights, two velocities
if your units don't match, you get nonsense
oh this is wisdom
Basically you want to add two compatible things together
acceleration is m / s² (distance / time²)
velocity is m / s (distance / time)
Can't add m/s² to m/s, two different things
so far this works pretty well for movement but I have noticed that at lower FPS your movement can rise decently above the movement speed
trying to apply this stuff
Acceleration is how much velocity is gained per second, so by doing acceleration * elapsedTime you get the velocity change during that time, which you add to your current velocity
I'd just use MoveTowards to accelerate the player as well
huh?
Then velocity is the distance gained during one second, so if you do velocity * elapsedTime you get the distance change during that time which you then add to your current position
As simple as that
(where elapsedTime is deltaTime basically)
well, do the math
if _walkAccel is 100 and you accelerate for 1 second, you'll get a velocity of 100 m/s
here are the real values btw
use MoveTowards instead
Vector3.MoveTowards(currentVelocity, inputDir * _movementSpeed, Time.deltaTime * _walkAccel)
(i made up names here)
MoveTowards won't go too far
well,
the reason I'm not doing that is because you told me earlier that in order to soft cap movement speed I should take the lower of the movement speed and the movement speed plus player input if the movement speed is too high
sure, and you can still do that
oh
use MoveTowards to compute a new velocity vector
then maybe clamp if it it's too long
i mean idk how to do this
this.
take the current velocity vector and move it towards the desired one
that's it
I'm not sure what to do for MaxDistanceDelta
that's the maximum distance it will move away from the first vector
if the vectors represent velocity, then...
that delta is the maximum change in velocity
no I mean- I used to just add (movementDirection * walkAcel) * (time.deltaTime)
i'm not sure what the equivalent with moveTowards would be
it won't be exactly equivalent
suppose you're walking right
your velocity vector is [1,0]
Now you want to walk up
Let's say deltaTime is 1
and that your movement speed is 1
Your code would do [1,0] + [0,1] = [1,1]
it would then need to clamp that to [sqrt(2), sqrt(2)] to get a vector with a length of 1
The next frame, it would add [0,1] again
It would keep getting closer and closer to [1,0]
compare that to MoveTowards:
Your velocity vector is [1,0]
You use MoveTowards to move towards [0,1]
I can't do the math on that in my head, but it'll move directly towards the up-vector
after two frames, it would be at exactly [0,1]
i'm sorry just none of this makes sense to me
i don't really understand what i'm doing rn
Vector3.MoveTowards(Vector3.zero, Vector3.right, 1);
Do you understand what this would return?
no, I do not
You're trying to move (0,0,0) towards (1,0,0) by 1 but I don't know what that would return
How far away is [1,0,0] from [0,0,0] ?
dunno, I don't really understand vectors all that well
I would assume 1
you take the difference in each axis and square them
add those up
and square root the whole thing
if they're only different on one axis, it's simpler: it's just the difference
so, yes, they're 1 unit apart
1 is the maximum distance to move by.
Vector3.zero and Vector3.right are also 1 unit apart
It returns [1,0,0].
Vector3.MoveTowards(Vector3.zero, Vector3.right, 0)
What does this return?
uhhhh 0,0,0?
right
we move by at most 0 units
Vector3.MoveTowards(Vector3.zero, Vector3.right, 0.1f)
what does this return?
[0.1,0,0]
right
we moved by at most 0.1 units
now, suppose we did this
Vector3 pos = Vector3.zero;
Vector3 goal = Vector3.right;
void Update() {
pos = Vector3.MoveTowards(pos, goal, 1);
}
What happens to pos?
it becomes [1,0,0] in 1 frame
right
Vector3 pos = Vector3.zero;
Vector3 goal = Vector3.right;
void Update() {
pos = Vector3.MoveTowards(pos, goal, Time.deltaTime);
}
And what does this do?
god only knows
assume Time.deltaTime is 0.1
if it stays 0.1 pos becomes [1,0,0] in 10 frames
yep
but it never stays constant so it confuses me
it'll change by a variable amount every frame
but after one second, it will have moved by 1 unit
if you're at 10 FPS, it moves by 0.1 per frame
if you're at 1000 FPS, it moves by 0.001 per frame
10 * 0.1 = 1
1000 * 0.001 = 1
same outcome.
now, a rephrasing
Vector3 velocity = Vector3.zero;
Vector3 playerInput = Vector3.right;
void Update() {
velocity = Vector3.MoveTowards(velocity, playerInput, Time.deltaTime);
}
I changed nothing but names.
it gets smaller relative to how high the fps gets
huh
interesting
right. it's how much time passed in the last frame.
velocity is set to velocity moved towards player input by some amount
so if it's [0,0,0] and input is [1,0,0] in 1 frame uhhhh
idk
since it can be variable
you don't know the exact amount of movement
but it'll be enough that, after one real-world second, velocity will have changed by 1
after one frame, velocity will be [Time.deltaTime, 0, 0]
each frame will add a variable amount to the velocity vector
until it reaches [1,0,0]
then it stops
because playerInput is [1,0,0] and we're moving towards it
if you assume that we're running at exactly 100 FPS, velocity will be 0.01, then 0.02, then 0.03, then 0.04, ...
but what if the fps varies a lot?
then the amount we add varies a lot
but remember: if deltaTime is high, we're getting only a few updates per real-world second
if it's low, we're getitng many updates per real-world second
0.1 * 10 = 0.01 * 100 = 0.001 * 1000
now, this doesn't mean the outcomes will be exactly the same
you're going to use this velocity to move the player
imagine the game is running at 1 FPS
the player will move by 0 meters per second in one update
then by 1 meter per second in the next update
that's gonna be different from moving by 0, then 0.1, then 0.2, then 0.3, ...
i follow this logic so far
this is some random picture I grabbed from a page about calculus
imagine you want to know the area under that function
low framerate = wide rectangles = big error
high framerate = small rectangles = small error
There are ways to deal with this, but to be honest, I've never done it before lol
for a visual intuition, at least..
you can be more clever about it
ignore the equation vomit
Anyway.
yeah this means nothing to me
The logic above works identically for changing your velocity and changing your position.
i probably shouldn't have brought up error at all; i've never worried about it myself
i ain't writing a whole physics engine
your acceleration tells you how quickly your velocity changes
your velocity tells you how quickly your position changes
now, you probably won't use MoveTowards to change your position, because there isn't a position you're trying to reach.
you just know how fast you're going; that's it
velocity = Vector3.MoveTowards(velocity, targetVelocity, accel * Time.deltaTime);
position += velocity * Time.deltaTime;
- change your velocity based on your acceleration (moving towards a target)
- change your position based on your velocity
well uh
i want your velocity to change by a walk acceleration value up to a walk speed, and just by holding WASD you should stay at walk speed
and it should be reduced by a decently large deceleration value
so, to do this I should
-slow the player down by a deceleration value
-take the player's input (normalized vector) and multiply it by walk acceleration
-add this to the player's current velocity
-if the magnitude of the new velocity value is higher than walkSpeed, take the lower of the two values
-move the player by their current velocity
so (simplified) mathematically:
Vector3.MoveTowards(velocity, vector3.zero, decel * time.deltatime)
Vector3.MoveTowards(velocity, input * walkAcel, time.deltatime)
take the lower of this value and normal velocity,
controller.move(velocity * time.deltaTime)
will this approach prevent the weirdness at lower fpses?
The code looks reasonable, except for "take the lower of this value and normal velocity,"; what is "normal velocity"?
velocity before you added player input
ah, okay, yeah, that's reasonable
The other thing I might change is:
only actually apply the deceleration if you aren't trying to move
Vector3 decelVel = ...
Vector3 playerMoveVel = ...
if (input.magnitude < 0.01f)
velocity = decelVel;
else if (playerMoveVel.magnitude > speed)
velocity = decelVel;
else
velocity = playerMoveVel;
oh, and one error
Vector3.MoveTowards(velocity, input * walkAcel, time.deltatime)
I think you wanted
Vector3.MoveTowards(velocity, input * walkSpeed, walkAcel * time.deltatime)
The first one would slowly move towards a very very long vector!
actually wouldn't it be Vector3.MoveTowards(velocity, velocity + input * walkSpeed, walkAcel * time.deltatime)
No, the second argument is where you want to end up
It should have nothing to do with your current value
If I'm holding up, I want to move upwards
now, it will take several frames to start moving upwards, because we only change the player's velocity by a little bit each frame
but my goal is to be moving purely upwards
so, the second argument should reflect that
Vector3.MoveTowards(from, to, amount);
i think that makes sense
just basing it off titanfall where you constantly decelerate and have to negate it through various means haha
oh yeah, you can definitely have some drag
but you probably want to have a much stronger decel when you aren't inputting anything
you can mess around with the values to get something that feels good
we use MoveTowards because the player has a very specific velocity they want
If this was a space game, where you just fired thrusters to move, you would not do this
there would be no target velocity; you'd just add the acceleration from the thrusters every frame
This is also why you don't use MoveTowards for the position
there is no target position
smart
ohhh okay!
omg crux tsym for all of this,
it works a lot better now from preliminary testing and that was def the hardest part
just need to figure out how to make WASD relative to your facing angle because mouselook still has you moving in cardinal directions haha
nice (:
Try using transform.TransformDirection . It turns a local direction into a world direction.
there is an odd stutter when you move around visually tho,
can't tell if that's an editor thing
Try full screening the game view
my HDRP game runs twice as fast without the editor interface getting drawn
how do I fullscreen haha
Double click on the game tab
Stutter can also be caused by the camera not moving at the same cadence as the player
e.g. camera goes in FixedUpdate, player goes in Update
You're using a CharacterController, right?
nah, it was just an example
I know Cinemachine has an option for it
Update is the most reasonable choice. You want to move the camera every frame
tbh idk how this works
in fact, even if the rest of the player is completely physics based, you still probably want to do camera rotation in Update
but it does seem stuttery
and yes I am using a charactercontroller
one thing to try is to simplify the movement as much as possible
e.g. just move by Vector3.right * Time.deltaTime and skip literally everything
see how it looks and feels
wdym by this?
replace all of your movement logic with controller.Move(Vector3.right * Time.deltaTime);
so that the player automatically slides right
see if it looks stuttery
the camera is what seems stuttery,
it's hard to describe
looks fine moving around normally
it stutters when you rotate?
yeah, it's kind of necessary
here, uploading
university wifi so itll be about 30 seconds
it just feels not quite smooth, in a weird way
80-90
what's the rest of the player? that's the upper half
The extra capsule collider on the player could be causing problems. Although, I don't THINK a character controller can hit its own object's collider like that
and the rotation still looks funny, so it's not just that
weird
how do you compute _playerLook.x and y?
I have a hunch
it's just taken from the new input system every update
can you share the entire script
uhhh sure
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
here's the input script
is PlayerInputSystem the result of using that "Generate C# Class" option?
also, I see why you're getting the null ref
yeh
when an object is created, Awake, followed by OnEnable, run immediately
Start runs before the first Update
so OnEnable went off before Start
my rule of thumb: Awake is to set yourself up, and Start is for when you need to talk to other objects
anyway, that looks ok
I thought you might have been having yet another fun time with Time.deltaTime
mouse input is a distance, so you don't do anything to it
I did this all the time until I finally tracked down why my view was randomly flying really far
real!
it's a bit annoying to fix if you want both controller and mouse input
the solution is to add a processor to the controller input that multiplies in deltaTime
i followed a tutorial for it
a while back
and the tutorial did it that way (put it in OnEnable)
so that you always receive a delta
mine threw a nullref so i patchworked a solution
ahh ok
will keep in mind
any clue here as to why it's weirdly stuttery?
anyway, other rotation issues
try doing a similar thing to rotation: get rid of player input entirely
just rotate by, say, 10 * Time.deltaTime
one confusing thing here is the use of _xRot and _xSens
_xRot is your rotation on the X axis
_xSens is your horizontal input sensitivity
I would rename _xRot to pitch
you pitch up and down
you commonly split rotation into two pieces
i just had it for testing initially
The entire player should spin around when you look left and right
But the player shouldn't tilt forwards and backwards when looking up and down
that'd be weird
indeed
You also have different rules for pitch and yaw
pitch can't go past a certain angle
or you'd go upside-down
but you can freely spin in circles forever
so, the code does two different things
- for pitch, it remembers the angle you want in a field. every frame, it adds your vertical input, then sets the camera's local rotation
- for yaw, it doesn't remember anything. it just takes your horizontal input and spins the entire player by that much
i would prefer to do it myself but i like. do not know how. and if i cannot figure out basic momentum based movement i cannot do mouselook either
X is the left-right axis
so a local rotation on the X axis pitches you up and down
Y is the up-down axis
a local rotation on that axis spins you
Z is the forward-back axis
it gives you motion sickness
doing this rn
it looks good
no stutter
I wonder if your mouse input isn't coming in every frame
here's a thought -- do Debug.Log($"{mouseX} - {mouseY}"); at the top of MouseLook
if you've never seen that before, $"this is string interpolation"
it lets you put variables right into the string
ik what string interpolation is :)
i picked it up from one thing you sent me
...hm, that seems about as juddery to me
It doesn't look like 90 FPS
ah, that might be the recording
If it's recording at 60 FPS, I will see doubled frames
yeah thats recording
here, do this somewhere
Application.targetFrameRate = 60;
that will clamp it to 60 fps
rela
you can undo that later by setting it to 0
ok windows defaults to 30
i fixed that making it 60, and i'll set the fps
one second
oh yeah, that'd make it look stuttery
30 fps is crunchy
you might try the Recorder package later
you just hit F10 and it captures the game view
here's just the rotation at 60fps
i am moving lol
anyway, put it back to normal and see if the stuttering is visible
so you can see the cube and so you can see how it looks fine when moving
oh god
peep this
it's VERY obvious at 60fps
okay that looks really familiar now
Is it fine if you're only moving or only looking?
yeah more or less
looking looks a bit off, moving seems fine
both at once looks awful
I had this problem when I was using an alternative CharacterController that only updated in FixedUpdate
but that's not the case here
can you send the player script?
player
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
player movement core
zooped
shush you
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
back in buisiness
tried a few different mouselook scripts with no luck sadly
a little thing to try: lock the framerate to 50
as stuttery as ever haha
expected; that would change things if this was somehow related to fixedupdate
does anything else read the look input?
i need to go test this properly; I'm not sure if a Delta input builds up values over several frames
InputHandler just calls ReadValue and passes it to ProcessLook, that's all
i can hand over the project if that helps haha it has nothing
Odd
This seems to have MUCH less stutter instead of going through input system
That is odd.
What the hell? This seems extremely smooth
That's all I changed
Yeah this looks perfect
So the issue somehow is in the value being read?
it's possible that RoxanneMovement is updating before InputHandler, but that shouldn't cause stuttering
you'd get just an extra frame of input latency
yeah, that shouldn't be causing this level of weirdness
I'd log the vector2 you get when reading the "Look" action
On it
it ought to be roughly constant as you move your mouse
so run the game, slowly move the mouse for a while, stop the game, and look at the middle of your logs
if it was zero every other frame, things would look mostly OK until you were both moving and looking, since you'd then see two jarringly different kinds of motion
it reports around -1 when i move the mouse slowly
perhaps it's a normalized vector for some reason?
make sure you have Collapse off btw
no
ah that's better
Moving it slowly it maintains around (2,0)
Swinging the cursors spikes it to around 50 for a moment then goes to 0 when I let go
Seems reasonable?
and if you go back and look, there aren't random dips?
specifically in the middle of a long slow movement
Dips?
If I move the cursor super slowly it reads 0
But other than that no
No random dips I can see
I had it read back both input systems - the new input system has larger numbers, but they seem relatively the same
what if you pass the old input system's values into the HandleLook method?
Yeah it's relatively identical
er, ProcessLook
If I do, the camera is smooth
i wonder if it's just because the sensitivity is way higher on the new input system's values
Nah I multiplied the old ones by 3 and 5 to match it aprox and it's still smooth
I read that the old input system multiplies mouse inputs by 0.05f, so it'd be off by a factor of 20
I am stumped, though. I guess I could look at the whole project
Let me know if you're still willing to take a look
The problem is more-or-less solved thanks to just, not using new input system