Hi i’m trying to create rail grinding for my game and i’m currently stuck on trying to align the player to the part when touching it
is there any way i can try achieving this?
I made a script that changes the CFrame of the HumanoidRootPart and then welds the character to the rail part. After that it calls a move function that moves the character on the rail by changing the C0 of the weld. It changes the direction that the character faces and moves to when the player turns their camera enough.It uses Humanoid.Walkspeed for the movement speed.It uses raycasting to check if the character is still on the rail. If it isn’t it detaches it by destroying the weld and doing some other things. It also does this is the character dies.
I’m not sure what is the exact behavior you want, so you might need to modify this. If you only wanted a way to attach the character to the track, you don’t need the move function, just detach it somewhere else in the code. This script only works properly if the Size.Z of the part is its largest size value and Size.X and Size.Y are the small values. This should work even if the part is rotated. It may look weird if it’s been rotated too much, though. I have noticed that setting Humanoid.Platformstand to true doesn’t work when the character hits the part while jumping and even if I tried to change it in a Stepped loop after that, it didn’t work. However, it works if you are walking when you touch the part.
local RunService = game:GetService("RunService")
local COOLDOWN = 1
local RAIL_ANIMATION = nil
local trackPart = -- reference to the track part here.
local cantBeWelded = {}
local railAnimTracks = {}
local function detachCharacter(char, hum)
trackPart[char.Name]:Destroy()
hum.AutoRotate = true
hum.PlatformStand = false
railAnimTracks[char.Humanoid] = nil
if COOLDOWN > 0 then
wait(COOLDOWN)
end
cantBeWelded[char] = false
end
local function moveChar(char, hum, hrp) -- this function takes care of moving and deataching the player
if RAIL_ANIMATION then
local railAnimTrack = railAnimTracks[hum]
if not railAnimTrack then
railAnimTrack = hum:LoadAnimation(RAIL_ANIMATION)
railAnimTracks[hum] = railAnimTrack
end
railAnimTrack:Play()
end
local weld = trackPart[char.Name]
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {char}
raycastParams.IgnoreWater = true
local _, delta = nil, 0
while char.Parent and hum.Health > 0 do
-- move the character
if hum.MoveDirection ~= Vector3.new() then
-- check if the direction should be changed
if hrp.CFrame:ToObjectSpace(hrp.CFrame+hum.MoveDirection).Z > 0 then
weld.C0 *= CFrame.Angles(0, math.pi, 0)
end
weld.C0 *= CFrame.new(0, 0, -hum.WalkSpeed*delta)
end
-- check that the character is still on the track
local rayDirection = trackPart.CFrame*Vector3.new(0, 0, (trackPart.CFrame:Inverse()*hrp.CFrame).Z)-hrp.Position
local raycastResults = workspace:Raycast(hrp.Position, rayDirection, raycastParams)
if not raycastResults or raycastResults.Instance ~= trackPart then
detachCharacter(char, hum)
return
end
_, delta = RunService.Stepped:Wait()
end
-- the code will only reach this if statement if the humanoid has dies or the character was removed
if trackPart:FindFirstChild(char.Name) then
detachCharacter(char, hum)
end
end
local function onTrackTouched(hit)
local hitParent = hit.Parent
if cantBeWelded[hitParent] then
return
end
local hum, hrp = hitParent:FindFirstChild("Humanoid"), hitParent:FindFirstChild("HumanoidRootPart")
if hum and hrp then
cantBeWelded[hitParent] = true
hum.AutoRotate = false
hum.PlatformStand = true
-- position and rotate the character correctly
local trackPartCf = trackPart.CFrame
local relCF = trackPartCf:ToObjectSpace(hrp.CFrame)
local newHrpCf = trackPartCf*CFrame.new(0, hum.HipHeight+hrp.Size.Y/2-trackPart.Size.Y/2, relCF.Z)
if hrp.CFrame:ToObjectSpace(hrp.CFrame+hum.MoveDirection).Z > 0 then
newHrpCf *= CFrame.Angles(0, math.pi, 0)
end
hrp.CFrame = newHrpCf
-- create a weld that prevents the character form being moved normally
local weld = Instance.new("Weld")
weld.Name = hitParent.Name -- character's name
weld.Part0 = trackPart
weld.Part1 = hrp
weld.C0 = trackPart.CFrame:ToObjectSpace(hrp.CFrame)
weld.C1 = CFrame.new()
weld.Parent = trackPart
-- start moving the character
moveChar(hitParent, hum, hrp)
end
end
trackPart.Touched:Connect(onTrackTouched)
Exactly what i was looking for. Thank you so much!