Ok so I’ve made a skateboard, all good but it just keeps on tipping over! I’m not quite sure what im doing wrong :\ I’m using a PID controller to attempt to keep the player balanced but like how the video shows, it just tips over. BTW the parts where i go upright are using a bodygyro, i dont want to switch to a bodygyro as they limit the players movement too much. I am using RoPID by BRicey763.
local PID = require(game:GetService("ReplicatedStorage").RoPID)
local rs = game:GetService('RunService')
local tune = require(PID.Util.Tuner)
local primary = script.Parent.PrimaryPart
local hrp = primary.Parent.Parent:WaitForChild("HumanoidRootPart")
local attach = Instance.new("Attachment")
attach.Parent = hrp
local vf = Instance.new("VectorForce")
vf.Parent = attach
vf.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
vf.Attachment0 = attach
vf.Force = Vector3.new(0,0,0)
local bpid = PID.new(20, 10, 10 , -1000 ,1000)
local tuner = tune.new("bpid", bpid)
local tiltaim = 0
rs.Stepped:Connect(function(et, dt)
local output = bpid:Calculate(tiltaim, hrp.Orientation.Z,dt)
vf.Force = Vector3.new(output, 0 ,0)
end)
You should debug it further by visualizing the force as a vector. Then make sure is the direction of the force reasonable? Is the amount of force/magnitude sufficient?
the fix was to make the output force negative to make sure it is in the right direction forcing the part up rather than pushing the part further downards.
vf.Force = Vector3.new(-balanceForce,0,0)*mass
the PID coefficients could be better but yeah here reproduction file with a dummy part. Simply run and rotate the part.
Edit: Here is a version with the force visualization I was talking about to better see the force and the direction.
Yeah, you can just create an attachment in Terrain then with the primary axis property it will align the skateboard attachment0 with the terrain attachment0 on the y axis only.
I think i got the force working, instead of using a serverscript i put it on a local script but it still gets confused when youre upright and keeps giving you force, also i have to ask if you know how to make it more responsive. Im not sure if i want to mess with using the orientation because that seems like it is more instant and sort of clunky / not dynamic idk i could be wrong
Here is an example of aligning the y axises only with align orientation. There is also no oscillation because align orientation solves the dampening problem already:
local attachTerrain = Instance.new("Attachment",workspace.Terrain)
attachTerrain.WorldCFrame = CFrame.fromOrientation(0,0,math.rad(90))
attachment.CFrame = CFrame.fromOrientation(0,0,math.rad(90))
local alignOrientation = Instance.new("AlignOrientation")
alignOrientation.MaxTorque = math.huge/2
alignOrientation.PrimaryAxisOnly = true
alignOrientation.Attachment0 = attachment
alignOrientation.Attachment1 = attachTerrain
alignOrientation.Parent = part
Align orientation sort of works like a bodygyro which isnt what im look for, in this video you can see that the player wont be placed on the ramp correctly
Well the current method of setting the target orientation goal to 0 wouldn’t work too well, because the person will be tilting on the ramp like so:
In the meanwhile you can more readily fix the align orientation method by applying less force or even raycasting downwards to get the new surface normal.
I’m not sure if you’re still having trouble with this, but if you used Rays, you might be able to solve your ramp problem. BodyGyros are absolutely the way to go, but you’d need to fire a ray down from the character to set it.
One way you could do this is like this:
local origin = root.Position
local direction = Vector3.new(0, -4, 0)
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances = {character}
local result = workspace:Raycast(origin, direction, params)
if result then
bodyGyro.CFrame = CFrame.new(Vector3.new(), result.Normal) * CFrame.Angles(math.rad(-90), 0, 0)
end
Just replace the variables with whatever you’re using in your script and it should work. If not, I have a few other ideas that might work. I’ve never worked with RoPID before, so I don’t know much about that. I’ll try to learn it, so I can help you if the BodyGyro doesn’t work.
Oh, I forgot one other thing. You’ll want to set the BodyGyro’s MaxTorque to Vector3.new(10000, 0, 10000) or some other big numbers. The middle value’s gotta be 0, though, so you can turn.