hello! I’m making a rail-grinding system, but whenever I go on a separate rail, the character glitches through both rail’s corners.
Here’s the clip: Untitled - Clipped with Medal.tv
for a bit of context, my script makes it so that each corner is put in a table and assigned a number as its name. Depending on the direction the player approaches it at, the script moves the player through the table of corners until there are no more corners to go to. I believe the cause of the problem is that it’s somehow trying to move the player through every corner that is named the same (see how it prints each corner 5 times for some reason), which is related to how the table is made… but I’ve got no idea to fix it
Here’s the script:
local RepS = game:GetService('ReplicatedStorage')
local UIS = game:GetService('UserInputService')
local Players = game:GetService('Players')
local constraintTemplate = RepS.GrindrailConstraint
local usingGrindrail = false
local currentPart = nil
local velocity = 30
local segments = {}
local function GetDistance(segment)
local node0: Attachment = segment:FindFirstChild("Node0")
local node1: Attachment = segment:FindFirstChild("Node1")
return (node1.WorldPosition-node0.WorldPosition)
end
local function CreateConstraint(segment: Instance)
local node0: Attachment = segment:FindFirstChild("Node0")
local node1: Attachment = segment:FindFirstChild("Node1")
local newConstraint = constraintTemplate:Clone()
newConstraint.Parent = segment
newConstraint.UpperLimit = GetDistance(segment).Magnitude
newConstraint.Attachment0 = node0
end
local function SetSegmentsTouch(touch: boolean)
for i,segment in pairs(segments) do
segment.CanTouch = touch
end
end
local function StopGrindrail()
usingGrindrail = false
task.delay(.5, function()
SetSegmentsTouch(true)
end)
end
for _, rail in workspace.Rails:GetChildren() do
for i, segment in rail:GetChildren() do
segment.Name = "0"..i
segments[tonumber(segment.Name)] = segment
CreateConstraint(segment)
segment.Touched:Connect(function(hit)
local player = Players:GetPlayerFromCharacter(hit:FindFirstAncestorOfClass("Model"))
if not player and usingGrindrail == false then return end
SetSegmentsTouch(false)
currentPart = segment
usingGrindrail = true
local char = player.Character
local HRP = char.HumanoidRootPart
local humanoid = char.Humanoid
local dot = humanoid.MoveDirection:Dot(GetDistance(segment).Unit)
local velocityMultiplier = 1
if dot < 0 then
velocityMultiplier = -1
else
velocityMultiplier = 1
end
humanoid.AutoRotate = false
local grindrailAttachment = HRP.GrindrailAttachment
local index = tonumber(currentPart.Name)
while usingGrindrail do
local currentConstraint = currentPart:FindFirstChildWhichIsA("PrismaticConstraint")
currentConstraint.Velocity = velocity * velocityMultiplier
local currentConstraint = segments[index][currentConstraint.Name]
currentConstraint.Attachment1 = grindrailAttachment
local distance = 0
if index == 1 and velocityMultiplier == 1 then
distance = ((grindrailAttachment.WorldPosition - currentPart.Node1.WorldPosition).Magnitude)+2
--Now this also checks if you're moving forward because if you're going backwards then the index
-- will be 1 and it's gonna try to calculate the distance when it's unneeded
--Occasional stuttering : (
else
distance = currentConstraint.UpperLimit
--Should be smooth here
end
task.wait(distance/math.abs(currentConstraint.Velocity))
print(currentPart, index)
currentConstraint.Attachment1 = nil
if velocityMultiplier == 1 then
index += 1
else
index -= 1
end
currentPart = segments[index]
if index > #segments then
humanoid.AutoRotate = true
StopGrindrail()
elseif index < 1 then
humanoid.AutoRotate = true
StopGrindrail()
end
end
end)
end
end
print(segments)