So, I have an object that floats at a constant height using a BodyPosition that only applies force on the Y Axis. When I apply velocity to the object with a VectorForce, it moves like it were in space and doesn’t slow down unless it runs in to something. There’s no “atmosphere” or “air resistance” to slow it down, so I created this simple script to fix the problem:
(Side note, if there’s a better way of creating air resistance, I’d like to know. I tried doing something with a BodyVelocity set to zero and got undesirable results)
So, getting to my real issue here, the object is a “vehicle” of sorts that the player controls and is essentially the player’s character in this game, so I figured it would be a good Idea to set the network owner of the the vehicle’s parts to the player that owns it for all the same reasons a player would usually have network ownership over their normal character. However, when I do this, the script above no longer works, and I’m back to having the vehicle handle as if it were in space again.
Why does changing the network ownership nullify this script and how do I fix it?
But I’ve also tried running the same script from a local script inside the player starter scripts (with the paddle variable being updated to the correct path) and it still didn’t work.
It’s not clear how you’re dividing client and server responsibility, but I should mention that when the client is the network owner of parts, the server seems to get the wrong velocity for them.
I scripted something to have the player explode if they hit a wall too hard (indicated by deceleration) and even when compensating for low serverside character info update rate by recording deceleration over multiple frames players wouldn’t explode. I had to calculate velocity from changes in character position.
Also, a couple of other problems.
Your script would cause almost 90% of speed to be lost per second, that speed loss is per frame of which there are 60 in a second.
And it doesn’t account for framerate fluctuation.
A better script would be this:
paddle = script.Parent.Parent
airResistance = 0.965 --Speed loss per second
game:GetService(“RunService”).Heartbeat:Connect(function(timeStep)
paddle.Velocity = paddle.Velocity * math.pow(airResistance, timeStep)
end)
True, I didn’t think about fluctuating frame rate. By the way, I do actually want that much speed reduction due to the nature of the vehicle. It needs to slow to a stop within a second or so of the player releasing their controls on the keyboard. What you did has little to no reduction at all. But that’s fine, I should be able to figure out the math to keep a high speed loss reduction and be consistent even with fluctuating frame rates. Thanks for the tip.
Also, it seems I got the velocity updating from a local script working now with the network ownership assigned to player. I’m not really sure why either cause I don’t think i really changed much of anything, but oh well.
Okay, well I may have got that working, but for some reason the vehicle’s parts don’t seem to properly respect density values after the network ownership is set to the player… a small fast moving object with a density of 0.01 (with network ownership on the server) can hit the vehicle with a density of 100 (with network ownership by a player) and make it move significantly.
I love game development and then other times I hate it when things are super finicky and act strangely. Doesn’t seem to matter what platform either, I’ve done unity development and had the same love/hate relationship with it too
Maybe I can get away with the vehicles remaining on server network ownership…?
It seems as though you’re going through a lot of effort here to produce a not-so accurate representation of air resistance.
Air resistance is just another force; if you’re using a VectorForce in the first place, you can just add the vectors in order to get a more accurate result. In the real world, air resistance opposes the direction of motion at a magnitude equal to kv^2, where v is velocity k is a constant that varies based on surface area and air density. For all intensive purposes, it’s easiest to just play around with values of k to see what works best for you.
I don’t know how you’re setting the Force property of the VectorForce, but you should be adjusting the force itself instead of the velocity of the part, i.e.:
Force = OriginalForce - (k * Paddle.Velocity.magnitude^2) * Paddle.Velocity.unit
Where OriginalForce is the force calculated based on user input. If you don’t have any user input, OriginalForce should just be 0, and that should bring the vehicle to a stop.
I know I didn’t provide you with any real code, but it’s hard to be too specific without knowing exactly what your circumstances are. Hopefully this helped.
VectorForce seems to only add to the velocity of a part, it doesn’t subtract from the velocity if the force is less than the velocity. In other words, If you give an object Velocity with a VectorForce and then set the VectorForce to zero or less than the original velocity, it still continues with the same velocity. Hence why I was modifying the velocity directly. Maybe I’d have better luck with BodyVelocity, as I’m pretty sure it WILL also subtract from the part’s velocity to make the velocity match the force.
I figured there was probably some sort of formula for air resistance, but oddly enough, the way I did it seems to produce a fairly desirable result for what I’m looking for. But maybe it would be even better with the formula you provided, so I may give that a go and see if I like the results better. Thanks.
Objects only accelatate under a net force, so of course the velocity doesn’t change if you set the force to zero. Also, the behavior you’re talking about isn’t correct; the velocity doesn’t have a bearing on whether or not the force applies. A BodyVelocity also isn’t really what you’re looking for either, as it forces the velocity of the part to be what you set the Velocity property to, essentially making the VectorForce usless unless you want to eliminate it altogether.
I would really recommend checking out class documentation on the wiki and doing a little research on Newton’s laws of motion. Both of those things should help you out a lot.
That’s what I was suggesting, that maybe I should try BodyVelocity INSTEAD of VectorForce, and use your air resistance formula to decrease the BodyVelocity force when the player stops holding down controls to move the vehicle.
BodyVelocities only have a MaxForce property, which is the maximum amount of force that can be exerted on each axis in order to reach the desired goal Velocity. Changing that won’t do what you’re looking for. Also remember that force is directly related to acceleration, not velocity.
Okay, so you’ve managed to sufficiently confuse me. I don’t know if there’s been some miscommunication, or I’m just being slow to follow or what, but I am quite confused now.
Firstly:
Who said anything about changing MaxForce? BodyVelocity has a Velocity Property… Maybe I didn’t choose the right words when I said the following,
I probably should have said “to decrease the BodyVelocity’s Velocity.”
And secondly:
I feel like you completely contradicted yourself. First you said:
But then you said:
So yeah, I’m not entirely sure what your suggestion for me at this point is…
You’ve told me that I should adjust the VectorForce itself to stop the vehicle, yet you’ve also agreed that slowing the VectorForce to zero won’t stop the vehicle, and you also said that you don’t think BodyVelocity will do what I need… soooo uhhhh
It’s not contradictory, he’s recommending that you not manipulate velocity directly, just add a drag component to your force. So, just an example (with totally arbitrary numbers), supposed your player’s input to move the platform forward means you apply a force of 1000 in the direction they want to move. You add drag to this, which is a vector in the opposite direction, proportional in strength to the square of the current velocity, updated every frame. The faster they get going, the more drag there is, until eventually the drag gets to 1000 and you are at full speed (the fastest you can go with a motive force of 1000). When your player stops their input (releases the W key or whatever makes them go forward), that 1000 force they were applying goes instantly to 0, leaving only the drag component. The drag decays to zero as the platform slows. The key is picking the ‘k’ which gives the amount of drag you want, and is stable.
There are a few things to be aware of. Trying to make a control system of this type that uses only counter-acting force to quickly achieve a target velocity is not inherently stable in a discrete simulation. That equation for Force Xulp gives has Force calculated from velocity on the previous step, which was calculated from Force the step before that… a second-order difference equation. For small k, your platform will take a long time to coast to a stop. But for k too large, it can oscillate as it nears zero, or even fling your platform into the far lands. With FPS drops, which make the force get applied for longer than expected, an other wise stable choice of k can be unstable. So, it’s wise to guard against velocity overshooting or oscillating near zero. This doesn’t happen in the real world, because real physics doesn’t happen in 1/60-second discrete steps.
Oh, I think I understand now. Thanks for the more detailed example, that helped. So my question at this point though, if doing such a method is “not inherently stable”, and my current simple method of constantly reducing the velocity directly produces a fairly satisfactory result already, is it really worth trying to change to a more accurate model of air resistance if it might not be stable and I have to figure out how to “guard against velocity overshooting or oscillating near zero.”?
I wish roblox had something like the equivalent of Unity’s RigidBody property, “Drag” built into the properties for parts. I’ve built a floating vehicle in Unity and didn’t have to worry about it not slowing to a stop after releasing control inputs on the keyboard. Just had to play around with the drag value to get a desirable amount of drag.
No, it’s not worth the trouble to try to add drag as a force, IMO. Directly controlling velocity is numerically stable, and I think your original approach is sound.
It’s a game, so what feels right to players should trump accurate aerodynamic simulation. But, just so that you have the full picture, I’ll explain what your original solution is simulating, vs. how you would simulate air resistance more accurately through setting velocity. For the equations below, v(t) is velocity at t seconds after releasing the throttle, so v(0) is whatever speed the platform is going at the moment it starts to slow.
Your solution is the discrete implementation of v(t) = v(0)* 0.965^t
This is exponential decay, and could be re-written as v(t) = v(0) * e^(ln(0.965)t)
Exponential decay of velocity is characteristic of (and the solution for) something which is being slowed by linear drag. This is drag force that is proportional to velocity, Fd = -kv
Linear drag occurs usually with things being slowed by viscous fluids, or with laminar flow (no turbulence).
Drag of a vehicle through air is, as Xulp indicated, proportional to the square of velocity, Fd = -kv^2
The solution for this is not exponential decay, it’s hyperbolic decay. This takes the form v(t) = v(0) / (k * v(0) * t + 1)
Linear drag will bring something to a stop much quicker. Quadratic drag will have quicker deceleration at first, but will then gradually approach zero much more slowly. While the latter is more correct for drag in air, it might not feel right. So you know the options now, just use what looks best.