The title pretty much summarizes it, I’m making a simple rail grinding script but I cannot figure out how to place the player directly on top of the rail from any angle.
The bug is where I create the Position variable (Line 28), if the rail is not parallel to the z-axis then it just won’t position the player on top of the rail correctly. I don’t want the player to be at the middle of the rail, but, I’m not sure how to explain it, just on top of the rail from where the player is
How do I make it so that the player will be positioned correctly no matter the angle? Fixing the script or script examples would be very much appreciated.
local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local RailGrinding = false -- True if the player is grinding on a rail, if true the script will not run again until false.
local RailSpeed = 5 -- How fast the player moves along the rail
for _, BodyPart in pairs(Character:GetChildren()) do
if BodyPart:IsA("BasePart") or BodyPart:IsA("MeshPart") then -- Single out the children of the Character that are Body Parts (e.g legs)
BodyPart.Touched:Connect(function(Rail)
if not RailGrinding then
if Rail.Parent:FindFirstChild("_Rail") then -- Check if the touched part is a rail
RailGrinding = true -- If false, the thread will run again
--[[ CREATING VARIABLES ]]--
local BodyPosition = Instance.new("BodyPosition")
BodyPosition.P = 100000
BodyPosition.D = 5
local Sign = math.sign(HumanoidRootPart.CFrame.LookVector.X)
if Sign == 0 then
Sign = 1
end
local Direction = Rail.CFrame.LookVector:Abs() -- Get the direction the rail is facing, this is to move the player along the rail
local Position = CFrame.new(Vector3.new(HumanoidRootPart.Position.X, Rail.Position.Y + 5, Rail.Position.Z))
Character:PivotTo(Position)
local Looping = true -- If false, the loop will end
local Boosting = false -- If true, the speed will increase
--[[ MOVING THE PLAYER ]]--
while RunService.Heartbeat:Wait() do
local Movement = (RailSpeed/10)*Sign*Direction
Position += Movement
BodyPosition.Position = Position.Position
Character:PivotTo(Position)
local Params = RaycastParams.new() -- For Raycasting (Below)
Params.FilterDescendantsInstances = {Character} -- Ignores children of your character
Params.FilterType = Enum.RaycastFilterType.Exclude
--[[ KICK OFF THE PLAYER IF... ]]--
local RayCast = workspace:Raycast(HumanoidRootPart.Position, Vector3.new(0, -10, 0), Params) -- Cast the ray with params
if RayCast and RayCast.Instance then
if RayCast.Instance.Parent:FindFirstChild("_Rail") then
-- The ray hit a rail, update the Rail variable
Rail = RayCast.Instance
Direction = Rail.CFrame.LookVector:Abs()
else
-- The ray hit something other than a rail, kick off the player
Looping = false
end
else
-- The ray didnt hit anything, kick off the player
Looping = false
end
game:GetService("UserInputService").InputBegan:Connect(function(input,gpe)
if not gpe and input.KeyCode == Enum.KeyCode.Space then -- Jump off from the rail
Looping = false
end
end)
if Looping == false then -- What did this do again?
BodyPosition:Destroy()
wait(0.25)
RailGrinding = false
break
end
end
end
end
end)
end
end