Issues programming a Hover Board

Hello, I am trying to create a hoverboard script. What I want to occur is for the board to lift up to its hover height when it’s close to the ground, and float back down to the hover height when it’s above.

My design: A flat part with 4 thrusters attached to the corners. I already figured out the force each thrust needs to maintain to keep the board floating, regardless of the height.

Using my basic understanding of physics, I calculated the mass of the hoverboard with the 4 attachments and multiplied it by the gravity constant for Roblox. This got me:

F = (Mass of turqoise part + Mass of 4 blue parts)(196.2) = 4256.3628

I then divided the force by 4 to get the thrust each thruster needs to maintain which came out to be 1063.012. This force is applied in the Y direction using the BodyThruster’s Force property. I set the Force Property to (0,1063.012,0). Before adding in the code, I got the result shown below where the board is floating statically in the air.

Thrusters are blue, the hover pad is turquoise, the thrusters are all welded to the turqoise board.
https://gyazo.com/4fbd95c3b202d5853f8605106a121188

Now my next step is coding the board so that the thrust is determined based on the height. This is where my physics understanding comes short, unfortunately.

Logically, the thrust needs to be multiplied by a factor such that the thrust must be:

Equal to its self (1063.012) when I’m at the height I want (factor = 1)

Greater than 1063.012 when we are below the height (factor > 1)

Less than 1063.012 when are above the height (factor < 1)

The equation that I came up with was this:
https://gyazo.com/36e30a4af9941ffb208ce3815db26010

So, I set up a while loop that fires a ray straight down the hoverboard (Turquoise). Then I calculate the height (Distance between the board and whatever it touched) and use it to calculate the Thrust as shown below on lines 18 and 19.

rayCastParams.FilterDescendantsInstances = {script.Parent} -- Setting up the ray to ignore the hoverboard
rayCastParams.FilterType = Enum.RaycastFilterType.Blacklist

local Height
local Thrust
local MAX_VERT_HOVER_DISTANCE = 12.6
--local DAMPENING_CONSTANT = 0.6

while true do
	rayOrigin = script.Parent.Position -- Starting point of the raycast
	local rayCastResult = workspace:Raycast(rayOrigin,rayCastDirection)
	local hitWorldPoint = rayCastResult.Position -- The position of the point the ray hit
	
	Height = math.abs(hitWorldPoint.Y - rayOrigin.Y) -- Height calculated based on just the Y property of the origin and Y propert of the hit point
	Thrust = ((1063.012 * (MAX_VERT_HOVER_DISTANCE)) / (Height)) -- Thrust based on my chosen formula
	
	--Setting the thrust
	tableOfThrusters[1].BodyThrust.Force = Vector3.new(0,Thrust,0)
	tableOfThrusters[2].BodyThrust.Force = Vector3.new(0,Thrust,0)
	tableOfThrusters[3].BodyThrust.Force = Vector3.new(0,Thrust,0)
	tableOfThrusters[4].BodyThrust.Force = Vector3.new(0,Thrust,0)
	wait()
end

The result is shown below in this gif
https://gyazo.com/3f72c7cdbb2c5b7b5f9fd3fc9276769d

After looking at some scuffed hoverboard free models I noticed most of them use something called a dampening constant. Im not too familiar with the term but I assumed it was just a value that limits how fast a value is reached (The value we to reach is 1063.012). I implemented a dampening constant by just multiplying the formula by a random value, in this case I chose 0.6.

The new formula and code are listed below

https://gyazo.com/4049c000365df23bddba5daebf59e47e?token=70bd9c657dc23841e009476852923c05

local tableOfThrusters = workspace.HoverThrusters:GetChildren()

local rayOrigin

local rayCastDirection = Vector3.new(0,-1000,0) -- The distance and Direction I want my ray to travel

local rayCastParams = RaycastParams.new()

rayCastParams.FilterDescendantsInstances = {script.Parent} -- Setting up the ray to ignore the hoverboard

rayCastParams.FilterType = Enum.RaycastFilterType.Blacklist

local Height

local Thrust

local MAX_VERT_HOVER_DISTANCE = 12.6

local DAMPENING_CONSTANT = 0.6

while true do

rayOrigin = script.Parent.Position -- Starting point of the raycast

local rayCastResult = workspace:Raycast(rayOrigin,rayCastDirection)

local hitWorldPoint = rayCastResult.Position -- The position of the point the ray hit

Height = math.abs(hitWorldPoint.Y - rayOrigin.Y) -- Height calculated based on just the Y property of the origin and Y propert of the hit point

Thrust = ((1063.012 * (MAX_VERT_HOVER_DISTANCE)) / (Height)) * DAMPENING_CONSTANT -- Thrust based on my chosen formula

--Setting the thrust

tableOfThrusters[1].BodyThrust.Force = Vector3.new(0,Thrust,0)

tableOfThrusters[2].BodyThrust.Force = Vector3.new(0,Thrust,0)

tableOfThrusters[3].BodyThrust.Force = Vector3.new(0,Thrust,0)

tableOfThrusters[4].BodyThrust.Force = Vector3.new(0,Thrust,0)

wait()

end

The result is shown below
https://gyazo.com/f261f160cd4973e0d2f9535dc02f7339

I don’t understand the next step to this, as my physics knowledge is really lacking. I know eventually, I will need to code it so that the weight of the player is factored into the calculation of the thrust, but before I do that, I need to the board to be stable on its own.

The vision I want for the board is that when it dips down below the max height (12.6) I don’t want it to shoot back up past 12.6. It should stably reach the 12.6 height.

Physics lords help me, please.

Also as a side note: Has anyone ready Physics for Game Programmers and found it useful to development on Roblox?

3 Likes

It seems that whenever you get too close to a part it pushes it away I do not know in which direction.

When it is moving towards the terrain only some of the hoverboard is above or closer to it which causes it to push it away.

Your thrust formula is asymptotic, pretty much like f(x) = 1/x , which is very unstable. Try to think of a linear function which describes the difference of current and desired height.

2 Likes

In my function though, the variable Height is the difference between current and desired height. But I see how it gets unstable. As the height approaches 0 the thrust asymptotes. However, I didn’t think the relationship between height and thrust could be anything but asymptotic since they have an inverse relationship.

I’ll definitely think on this though, thank you.

Where does the ray start?
characters

At the position of the hoverboard. I fire one ray from the position of the hoverboard. I don’t know if it’s better to fire 4 rays from each of the thrusters, although does not instinctively seem good.

As far as I can see, the Height variable is merely the current height of your object. Also the relation of height/position and thrust/force is surely not inverse. It’s only like that because you wanted your equilibrium at 1 with no bias/offset.
In reality, force is the result of two differentiations of position by time.
Your 1063 force would rather fit in as an offset which applies permanently instead of making it a large scaling factor on an already nonlinear function.
You should be still looking for a linear solution.

1 Like

I am not understanding what you mean when you say height/position and downward thrust are not inverse. As height increases, downward thrust should decrease, and vice versa. Do you mean that the inverse relationship is not as simple as the formula I came up with? If so, then I agree.

There are numerous functions which satisfy your conditions:

Equal to its self x when I’m at the height I want (factor = 1)
Greater than x when we are below the height (factor > 1)
Less than x when are above the height (factor < 1)

For example:
thrust = math.tan(heightDiff) + 1
You should use one which is linear and continuous unlike your current one.

1 Like

Thank you for the explanation. Another equation that I came up with that showed up as linear on Desmos was 1075.612 - height. The general formula is in the gyazo below.

https://gyazo.com/c3ef5903c5f5523073742c804288fe89

As the height increases thrust decreases and vice versa. Also, at a height of 12.6 we reach equilibrium (the thrust is equal to 1063)

This made the hover board a lot more stable as you can see in this gyazo below.
https://gyazo.com/ccebfd4cc7df3ad416781d3d71a0b172

Also in the code below I changed the thrust needed to 1037 because I attached new thrusters that had a different size so that I could verify that they are positioned correctly.
Therefore 1044 is the new offset/bias needed so that at a height of 7.35 equilibrium is achieved

local platform = script.Parent
local tableOfThrusters = workspace.HoverThrusters:GetChildren()
local bodyGyro = platform.BodyGyro
bodyGyro.CFrame = platform.CFrame
local rayOrigin 
local rayCastDirection = Vector3.new(0,-1000,0) -- The distance and Direction I want my ray to travel
local rayCastParams = RaycastParams.new()
rayCastParams.FilterDescendantsInstances = {script.Parent} -- Setting up the ray to ignore the hoverboard
rayCastParams.FilterType = Enum.RaycastFilterType.Blacklist

local Height
local Thrust

--Constants
local MAX_VERT_HOVER_DISTANCE = 7.35
local DAMPENING_CONSTANT = 0.6
local EQUILLIBRIUM_THRUST = 1037.054219

while true do
	rayOrigin = platform.Position -- Starting point of the raycast
	local rayCastResult = workspace:Raycast(rayOrigin,rayCastDirection)
	local hitWorldPoint = rayCastResult.Position -- The position of the point the ray hit
	
	Height = math.abs(hitWorldPoint.Y - rayOrigin.Y) -- Height calculated based on just the Y property of the origin and Y propert of the hit point
	Thrust = (EQUILLIBRIUM_THRUST + MAX_VERT_HOVER_DISTANCE)-Height
	--Thrust = ((1063.012 * (MAX_VERT_HOVER_DISTANCE)) / (Height)) * DAMPENING_CONSTANT -- Thrust based on my chosen formula
	
	--Setting the thrust
	tableOfThrusters[1].BodyThrust.Force = Vector3.new(0,Thrust,0)
	tableOfThrusters[2].BodyThrust.Force = Vector3.new(0,Thrust,0)
	tableOfThrusters[3].BodyThrust.Force = Vector3.new(0,Thrust,0)
	tableOfThrusters[4].BodyThrust.Force = Vector3.new(0,Thrust,0)
	wait()
end

There is still one more issue where the hoverboard will tilt towards a certain direction. I verified twice now that the thrusters are all in positions that are an equal distance from the center of the hoverboard.

https://gyazo.com/a5b6da9035f5584df738f35eb042a238

I decided to patch this issue using a body gyro whose CFrame property has been set to that of the turquoise platform and whose Max force property is 0 on all axis except the X because I only want to stop the hoverboard from tilting. It worked.
https://gyazo.com/ccebfd4cc7df3ad416781d3d71a0b172

However, there is still slight movement in the X direction as shown in the gyazo below. The gyazo shows me printing the X position of the hoverboard once per second. It should not be changing on the x but it is.

https://gyazo.com/5c5a09aeac4510544f51137abb1204b4

I’m thinking it has to do with the fact that the thrust is not being set at the same time. I’m considering wrapping the thrusts in their own coroutine and seeing if that helps.

Thanks for the explanation again, that really helped.