Side point(?): Currently I’m doing it with Roblox constraints, but I’d rather not do it this way if you can come up with a decently “physically accurate” simulation
I’m using AlignOrientation and AlignPosition constraints right now to get the nice Roblox PID, and I think it works amazingly except I’m stuck on how to handle the case when the hover board is above the max height
I feel like it should let the hover board free fall and catch it at just the optimal time to reach the target height (if it were a spring, I would say I want it to be critically damped)
What I currently do is disable the AlignPosition when it is above the desired height, but that causes problems because if it is just at the height it will occasionally dip down due to overshooting upwards since I disable the AlignPosition, and if it is above the height, since the constraint only starts after it is not above the height, it will collide with the ground E.E
local ignore=env.Ink.Black{workspace.Debris}
local cast=env.Spatial.Cast
local v3=Vector3.new
local cf=CFrame.new
local height=5
local board=script.Part:Clone()
board.Parent=workspace.Debris
local move=board.Move
local goal=board.Goal
move.Position=v3(0,-height,0)
goal.Parent=workspace.Terrain
env.Stepped:Connect(function(dt)
local hit,h,n=cast(board.Position,-move.WorldAxis*height,ignore)
if hit then
board.AlignPosition.Enabled=true
goal.CFrame=CFrame.Angles(math.pi/2,0,0)*cf(v3(),n)+h
else
board.AlignPosition.Enabled=false
end
end)
Many on this forum have different opinions about how to handle physics like this… Some may call me masochistic, but I enjoy manually CFraming effects like this.
If it were me, I’d run in a tight loop every frame client side, taking in these things:
The desired height range (if this isn’t predefined)
the current board height
the current board velocity
I’d also have the max upward acceleration noted somewhere in the script. Then I’d update the board’s velocity and position every frame. When above the desired height, I’d calculate when I need to start applying that upward acceleration to stop the board’s fall just below the maximum desired height. I’d set the angle of the board as a function of the deceleration of the board on the xz plane. Perhaps the square root of the deceleration in the relative z direction (scaled by some appropriate constant) would make a great pitch for the board, and likewise in the x direction a roll.
Could you provide specific equations for how you would model it? Particularly how you would account for the changing terrain and maintaining gravity as an always acting force
In some games you may be able to use game specific knowledge to know the ground height, allowing us to figure out the distance from the board to the ground h. If not, then a single raycast from the center of the board should be sufficient.
As for the stopping in time while falling. The gravitational constant g in Roblox is 196.2 studs/s^2. Given the board’s current velocity v, the maximum upward acceleration uA, and the difference between the current height to the maximum desired height ∆h, the time required to cancel the falling velocity is -v / (uA - g). Plugging this time into the equation ∆h = (g + uA)/2 * t ^2 + v * t I get that the required stopping acceleration is uA = g ± √(g * v^2 / ∆h) Does that look right to you guys? Each frame this can be calculated with an updated current velocity and height. If the required acceleration is ever greater or near the maximum acceleration, then apply the acceleration to the velocity each frame and the board will stop in time.
Now, If you want the board to collide with other things (which is probable) then I’d use a VectorForce to apply the upward thrust. You’d just need to factor in the board’s mass and optionally the mass of whatever it is carrying (it look like it was struggling with heavier loads if you don’t factor it in).
But then again, some people think I’m crazy. I just think things like this are fun. ^.^
Damping the velocity seems more like a hack to me because I think you can’t dampen in real life?
Also why do you use self so much xd? Is it cuz u dont want to think of a variable name or what
I’m not sure how true your math is, I think you changed how you define your variables midway through (specifically uA*)
Also you have to take into account reaching the target height isn’t good enough, you also want to have 0 velocity at the target height… and hitting the ground is out of the question (but dipping down and recovering is allowed)
And I think the solution should be somewhat optimal or you could just do nothing and arrive in infinite time
I feel like that’s wrong because you are assuming max acceleration(?) as uA but in reality it should be the current acceleration, which also happens to be what you are solving for?
I did
Damping the velocity seems more like a hack to me because I think you can’t dampen in real life?
Also why do you use self so much xd? Is it cuz u dont want to think of a variable name or what
I just use it because it is highlighted differently so I can clearly see references to the object itself and the damping and whatever is straight from roblox calcs and it is using a force not a spring/shock setup
Okay, I got a solid solution. I’ll write it more verbose this time:
given velocity studs/sec = acceleration studs/sec2 * t sec + init_velocity studs/sec
then when the desired velocity is zero: 0 studs/sec = acceleration studs/sec2 * t sec + init_velocity studs/sec
solving for the time to reach this desired velocity given any acceleration and initial velocity: t sec = -(init_velocity studs/sec) / (acceleration studs/sec2) = -init_velocity / acceleration sec
And given distance studs = 1/2 * acceleration studs/sec2 * (time sec)^2 + velocity studs/sec * time sec
We can find the required acceleration to travel a desired distance while arriving at our desired velocity at the same time by substituting time as solved above: distance studs = 1/2 * acceleration studs/sec2 * (-init_velocity / acceleration sec)^2 + init_velocity studs/sec * -init_velocity / acceleration sec
Giving shorter aliases to clean this up, we get:
d = a/2 * (-v / a)^2 + v * (-v / a)
-> d = a * v^2 / (2 * a^2) - v^2 / a
-> d = v^2 / (2 * a) - v^2 / a
-> d / v^2 = 1 / (2 * a) - 1 / a
-> d / v^2 = 1 / (2 * a) - 1 / a
-> d / v^2 = -1 / (2 * a)
-> -2 * d / v^2 = 1 / a
-> a = -v^2 / (2 * d)
And there we have it. Given any initial velocity and distance to cover, we can find the acceleration required to simultaneously cover the distance and cancel out our velocity at the same time. Applying these general concepts to this application is fairly straight forward, so I’ll leave it to you.
Edit: here is an article I found on it. The equations match.
you have your own damper to decay the force too so you are damping the bodythrust on top of the bodythrust.D property: local f = -stiffness*len-damping*self.Velocity:Dot(self.CFrame.rightVector)
also you use self as variable names for roblox instances (the “Hover” part), can you elaborate on why? (i think its kinda clean so I might wanna start doing it ;P)
And Body Thrusts do not have any damping. The script is also designed to make it so that the hoverpad does not push down toward the ground and instead falls (only applying levitational forces) and it also is a lot more stable than roblox springs. You also need to make multiple hoverpads and not hovergroups to keep the same config (welding together or etc should be fine). Theyre designed so that you could slap invisible ones on a car object (given the config is appropriate) and it would float.
Okay, I will try implementing this and let you know how it goes
My confusion with this method before was that I felt like it was relying on acceleration to find acceleration in that from the velocity equation you are finding T based on acceleration then you are using the T (which is based on acceleration) to find acceleration
I thought that this meant it was an iterative solution but I realize now that I was completely wrong because (this is the reason I think I was wrong, if I’m mistaken please correct me) you’re using the variables at the same time step to solve for the two unknowns, T and a - albeit you don’t care about T but you have the right amount of degrees of freedom with two equations and two unknowns
this doesn’t really work because you are solving for the time at which you make the velocity 0, and if the velocity is already 0, you wont move at all (even though you may not be at the desired height)
um no im solving for the spring force.
i thought that was extremely obvious considering a bodythrust applies a local force…
and being at the desired height does not matter, just raise the height or the stiffness and it will be more accurate.
Then gravity will continue to accelerate the board down until the last moment the board can pull out of it with the desired maximum force. Now that is an intelligent board! While it is possible to create an equation to tell us when we need to apply the upward thrust instead of an equation that is checked every frame, if external forces act on the board then the time to apply the upward thrust will change. Checking every frame seems like a less stateful and therefor less bug prone approach to me.