Jailbreak train platform system?

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
			if humanoid:GetState() == Enum.HumanoidStateType.Freefall or humanoid:GetState() == Enum.HumanoidStateType.Jumping or humanoid:GetState() == 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.

13 Likes

I apologize for necro posting but do you still need help with stopping the jittering of other players? I spent 10 hours trying to figure it out and I managed to stop it from happening.

If not this will be helpful for future readers.

In order to stop other players from jittering you must have the player who you see as jittering calculate a relative CFrame from the root of the train to their humanoidrootpart on their client after the train CFrame changed and then fire that relative value to the server where other clients can use it to determine that player’s location on the train.

Example:

Player Client:
HumanoidRootPart.CFrame = Rel * HumanoidRootPart.CFrame – setting player cframe
TrainEvent:FireServer(HumanoidRootPart.CFrame:ToObjectSpace(TrainCFrame)) – firing to server

Server:
TrainEvent.OnServerEvent:Connect(function(PlayerSent, Bool, CFrameSent)
local CharSent = PlayerSent.Character
if CharSent then
CharSent:FindFirstChild(“TrainPosition”).Value = CFrameSent
end
end)

Then inside your player client script have a something that searches through all the player’s characters with a for i,v in pairs loop and if that player is touching the train set their v.Character.HumanoidRootPart.CFrame to TrainCFrame* RelativeCFrame.Value:Inverse() – you may or may not need inverse(), I personally needed it for my case.

Note: I have CFrame values stored on every player’s character and when the server changes, It automatically changes it on every client

This will stop other players from jittering on your screen :sunglasses:

3 Likes

I also apologize for boosting this topic even further, but be warned, if you do this, you will be sending a request to the server every frame. This can be harmful considering the details ive found from other posts.

hey, do you know how to do the same thing but with everyplayer? (on the client of course)

Just do what @IXIKOBRAIXI did in the post 2 above yours.

Stop boosting almost 3-year-old posts guys.

Staff should have locked this like a year ago.

1 Like

I tried doing this but unfortunately all it resulted was the jitter looking even weirder

2 Likes

I’m sorry to boost this but if you want to implement the same system without the jitter you have to use what @noblemaxx did above, use body movers for the unanchored platform like the “AlignPosition” constraint (you can even tween it for smooth movement) and use the script only for jumps. That way the server handles the physical contact, and the client handles the movement in air, so there’s no jittering.

2 Likes

Greetings, May I know how this code works, So I can make better versions of it?

whats happening is your boat already moves players with it. What your trying to fix is when they jump to stay moving. Its doubling up the already moving physics with the scripts moving function cus when you jump you stay in place like its supposed to but standing it breaks

This just saved me so much time and effort, I’m not a very experienced scripter but this script seems to work extremely well for my use, thank you.