Jailbreak train platform system?

Did you ever figure this out?
Having similar issues

just wondering, How do you do that?

I’m having similar issues as well. Did he ever respond to you?

Nope, I’m still searching and experimenting as well

If you find anything can you let me know please? I’m browsing through so many posts and trying different things and I’ve yet to find anything :confused:

Hey, I took a look at the thread. I looked at what worked best for me. However there were some bugs with the LastPartCFrame not being reset, so I fixed it. Here is the code optimized to work with the new Raycasting method too.

Update: it can also check for HumanoidStateTypes

--[[
SETUP
1. Make a LocalScript
2. Put it inside of StarterCharacterScripts
3. Make a folder in workspace and call it "MovingObjects"
4. Put all your moving objects in that folder
5. OPTIONAL, the CheckStates variable will set the CFrame if the character's HumanoidState is not Jumping and not swimming 
]]
--BrahGames 07-27-2021 rewritten https://devforum.roblox.com/t/jailbreak-train-platform-system/236339
local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService('RunService')

local CheckStates = true
local LastPartCFrame
local LastPart
local Function
local Function2
function CFrameLogic(Raycast, CFramePart)
	--------------------------------------------------------------- MOVE PLAYER TO NEW POSITON FROM OLD POSITION
	if Raycast.Instance ~= LastPart then
		LastPart = Raycast.Instance
		LastPartCFrame = nil
	end
	local Train = Raycast.Instance
	if LastPartCFrame == nil then -- If no LastTrainCFrame exists, make one!
		LastPartCFrame = Train.CFrame -- This is updated later.
	end
	local TrainCF = Train.CFrame
	local Rel = TrainCF * LastPartCFrame:inverse()
	LastPartCFrame = Train.CFrame -- Updated here.
	CFramePart.CFrame = Rel * CFramePart.CFrame -- Set the player's CFrame
	--print("set")
end
Function = RunService.Heartbeat:Connect(function()
	--------------------------------------------------------------- CHECK PLATFORM BELOW
	-- Build a "RaycastParams" object
	local MovingObjects = workspace.MovingObjects --Make a folder and put all moving objects into it and call the folder "MovingObjects"
	local HumanoidRootPart = player.Character.HumanoidRootPart
	local humanoid = player.Character.Humanoid
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
	raycastParams.FilterDescendantsInstances = {MovingObjects}
	raycastParams.IgnoreWater = true

	-- Cast the ray
	local Hit = workspace:Raycast(HumanoidRootPart.CFrame.p, Vector3.new(0,-50,0), raycastParams) --Casts a ray facing down
	--------------------------------------------------------------------------------------------
	if Hit and Hit.Instance:IsDescendantOf(MovingObjects) then -- Check if the ray hits and if it hits an object inside of MovingObjects
		if CheckStates then -- check if the character is jumping
			if humanoid:GetState() == Enum.HumanoidStateType.RunningNoPhysics or humanoid:GetState() == Enum.HumanoidStateType.Running or humanoid:GetState() == Enum.HumanoidStateType.Landed or humanoid:GetState() == Enum.HumanoidStateType.PlatformStanding or humanoid:GetState() == Enum.HumanoidStateType.Seated or humanoid:GetState() == Enum.HumanoidStateType.GettingUp or humanoid:GetState() == Enum.HumanoidStateType.None or humanoid:GetState() == Enum.HumanoidStateType.Physics or humanoid:GetState() == Enum.HumanoidStateType.Ragdoll or humanoid:GetState() == Enum.HumanoidStateType.Dead then
				CFrameLogic(Hit, HumanoidRootPart)
			else
				LastPartCFrame = nil -- Clear the value when the player gets off.
			end
		else
			CFrameLogic(Hit, HumanoidRootPart)
		end
	else
		LastPartCFrame = nil -- Clear the value when the player gets off.
	end
end)
Function2 = player.Character.Humanoid.Died:Connect(function()
	Function:Disconnect() -- Stop memory leaks
	Function2:Disconnect() -- Stop memory leaks
end)
23 Likes

Just set the local variable CheckStates to false

But my train i’ll broke if i put it on that folder what can i do in that case?

1 Like

That would depend on how your train system works.

How would i do it for this piece of code?

(its for an obby part)

i changed the Hit.Name to find a value called “Moving” so it would be more customizable

The script doesn’t work when the player dies
Edit : Nvm i just had to put in StarterCharacterScripts

Is there a way to make this work for a model, instead of just a part??

Try welding all the parts in that model together and then placing this script in the part everything is welding. Or you could(I don’t know how well this is for performance) place the script inside every part, this is way is more tedious.

1 Like

Personally, I would try welding all the other parts together, this may make it easier.

make it detect the parent and see if its name is one it makes a platform

Hey, I have a spinning part and while it does make me stay on a little bit, it’s very jittery and sometimes I get teleported away.

Here is a GIF of me getting on the spinning platform:
https://gyazo.com/29f05fc0cdfffceb730ea64fb3c92b07

Here is my code, the script being located under starterplayerscripts.

local collectionService = game:GetService("CollectionService")
local player = game.Players.LocalPlayer
for _,spinningPart in pairs(collectionService:GetTagged("SpinningPart")) do
	local lastSpinningPartCFrame = nil
	game:GetService("RunService").RenderStepped:Connect(function()
		local speed = 60  / spinningPart.Configuration:GetAttribute("SpinSpeed")
		spinningPart.CFrame = spinningPart.CFrame*CFrame.Angles(0,math.pi/speed,0)
	end)
	game:GetService("RunService").Heartbeat:Connect(function()
		local character = player.Character or player.CharacterAdded:Wait()
		local root = character.HumanoidRootPart
		local r = Ray.new(root.CFrame.p,Vector3.new(0,-3,0))
		local hit,position,normal = workspace:FindPartOnRay(r,character)
		if hit and hit.Name == "SpinningPart" then
			if lastSpinningPartCFrame == nil then
				lastSpinningPartCFrame = hit.CFrame
			end

			local spinCF = hit.CFrame
			local Rel = hit.CFrame * lastSpinningPartCFrame:inverse()

			root.CFrame = Rel * root.CFrame
			print("set")
		else
			lastSpinningPartCFrame = nil
		end
	end)
end

I am trying to make a spinning part in my obby that keeps the player on it. It seems to be too big for body position or body angular velocity.

1 Like

Tried to converting this to use Collectionservice so i can just tag parts and itll work
decided to test on my boat tween test, and the player just spazzes out, any ideas?

Using a boat from Jailbreak to show off what i mean

My Code –

local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService('RunService')
local Tag = game:GetService("CollectionService")

local LastTrainCFrame

local Function
local Function2


Function = RunService.Heartbeat:Connect(function()

	--------------------------------------------------------------- CHECK PLATFORM BELOW

	local RootPart = player.Character.LowerTorso

	local Ignore = player.Character

	local ray = Ray.new(RootPart.CFrame.p,Vector3.new(0,-50,0))

	local Hit, Position, Normal, Material = workspace:FindPartOnRay(ray,Ignore)

	if Hit and Tag:GetTags(Hit,"Surface") then -- Change "RaftTop" to whatever the moving part's name is

		--------------------------------------------------------------- MOVE PLAYER TO NEW POSITON FROM OLD POSITION

		local Train = Hit
		if LastTrainCFrame == nil then -- If no LastTrainCFrame exists, make one!
			LastTrainCFrame = Train.CFrame -- This is updated later.
		end
		local TrainCF = Train.CFrame 

		local Rel = TrainCF * LastTrainCFrame:inverse()

		LastTrainCFrame = Train.CFrame -- Updated here.

		RootPart.CFrame = Rel * RootPart.CFrame -- Set the player's CFrame
		--print("set")

	else
		LastTrainCFrame = nil -- Clear the value when the player gets off.

	end

	Function2 = player.Character.Humanoid.Died:Connect(function()
		Function:Disconnect() -- Stop memory leaks
		Function2:Disconnect() -- Stop memory leaks
	end)

end)
1 Like

GetTags(instance) returns an Array. You should use HasTag(instance, tag) instead, this should fix the issue with the spazzing.

Also you have a memory leak with the Died connection, move that died connection out of the heartbeat loop.

1 Like

I slightly modified your script to work with unanchored objects moved by body movers. I changed the humanoid states to only work if you are falling or jumping, which lets Roblox handle the physical contact, and the script moves you back after you jump. I also adjusted the ray length, so it won’t push you back if you try to hop on from the front.

--BrahGames 07-27-2021 rewritten https://devforum.roblox.com/t/jailbreak-train-platform-system/236339 
--slightly edited to work with bodymovers and such /maxx

local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService('RunService')

local CheckStates = true
local LastPartCFrame
local LastPart
local Function
local Function2
function CFrameLogic(Raycast, CFramePart)
	--------------------------------------------------------------- MOVE PLAYER TO NEW POSITON FROM OLD POSITION
	if Raycast.Instance ~= LastPart then
		LastPart = Raycast.Instance
		LastPartCFrame = nil
	end
	local Train = Raycast.Instance
	if LastPartCFrame == nil then -- If no LastTrainCFrame exists, make one!
		LastPartCFrame = Train.CFrame -- This is updated later.
	end
	local TrainCF = Train.CFrame
	local Rel = TrainCF * LastPartCFrame:inverse()
	LastPartCFrame = Train.CFrame -- Updated here.
	CFramePart.CFrame = Rel * CFramePart.CFrame -- Set the player's CFrame
	--print("set")
end
Function = RunService.Heartbeat:Connect(function()
	--------------------------------------------------------------- CHECK PLATFORM BELOW
	-- Build a "RaycastParams" object
	local MovingObjects = workspace.MovingObjects --Make a folder and put all moving objects into it and call the folder "MovingObjects"
	local HumanoidRootPart = player.Character.HumanoidRootPart
	local humanoid = player.Character.Humanoid
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
	raycastParams.FilterDescendantsInstances = {MovingObjects}
	raycastParams.IgnoreWater = true

	-- Cast the ray
	local Hit = workspace:Raycast(HumanoidRootPart.CFrame.p, Vector3.new(0,-15,0), raycastParams) --Casts a ray facing down
	--------------------------------------------------------------------------------------------
	if Hit and Hit.Instance:IsDescendantOf(MovingObjects) then -- Check if the ray hits and if it hits an object inside of MovingObjects
		if CheckStates then -- check if the character is jumping
			local currentState = humanoid:GetState()
			if currentState  == Enum.HumanoidStateType.Freefall or currentState  == Enum.HumanoidStateType.Jumping or currentState  == Enum.HumanoidStateType.FallingDown then
				CFrameLogic(Hit, HumanoidRootPart)
			else
				LastPartCFrame = nil -- Clear the value when the player gets off.
			end
		else
			CFrameLogic(Hit, HumanoidRootPart)
		end
	else
		LastPartCFrame = nil -- Clear the value when the player gets off.
	end
end)
Function2 = player.Character.Humanoid.Died:Connect(function()
	Function:Disconnect() -- Stop memory leaks
	Function2:Disconnect() -- Stop memory leaks
end)

It gets buggy when I hop over the other player because the ray is not ignoring him, which turns the script off momentarily.

17 Likes