Jailbreak train platform system?

I gave badcc some insight on how we do our trains which he used to implement into jb’s new update, if he used exactly what we suggested, it’s actually pretty simple. For anchoring yourself to the train we just multiply the player’s rootpart CFrame to stay with the movement of the train car.


For anchoring other players, it’s a tiny bit harder but still pretty straight forward.

We essentially have a relative cframe from the center of the train car on the server and, after trains are cframed, have your client take that info, loop through other players and if they’re on a train then set their hrp.cframe to trainroot * relativecframe(the one sent from the server)

Hope this helps!


Yep! @tyridge77 tipped me off on the idea of CFraming the Character along with train movement. I didn’t originally want to do this because it’s kind of a fake momentum feel (if train goes around corner and you jump in the air, you’ll turn with it). But it makes everything feel super smooth, so I decided to finally add. Previously I was manually calculating Velocity/RotVelocity for every anchored train part, and the character would move along with it. This broke down a bit on Xbox, something is different there.

Now at start of train update frame I raycast down and check if player is standing on train, perform train update step, and check CFrame of that same part I raycasted earlier in frame. In my code above, that’s LastTrainCF and TrainCF. This way no matter what far the update step is, character moves with it. It’s beautiful. We also have some invisible platforms in between the train cars so that the ray hits it when you jump across.

In Tyridge’s fancy train demo he also broadcasts clients relative CFrame to train base part to every other client. I’m not doing this atm. You should show them some videos of yours @tyridge77 :smiley:


Yeah, there is, though as soon as you jump your removed from that platform, causing you to just fall back.


Thank you, very helpful.


What’s the LastTrainCframe? And what’s the need of inverting it? Thank you btw.


I think I understand this, and they can correct me if I’m wrong.

The system can be likened to a loop. Even if it is a connection to a RunService event, it acts like a loop so I will call it one.

Every loop, it moves players by the difference in position of the car between loops. So if the train car moved 14 studs in one loop (as an example), it would move the players inside 14 studs also. The script knows how far the train travelled in one loop by comparing where it was last loop and where it is this loop. So if it was at 45 studs last loop and it’s now at 59, 59-45 = 14 studs of movement. The delta is always calculated by taking the current position and subtracting the previous position.

This gets a little more complicated when 3D is taken into account. Since the cars exist in 6 dimensions (position and rotation), there needs to be a way to know exactly how the position and rotation changed. This is where CFrame comes in. CFrames are special and you can’t add or subtract them directly, but the basics of it is that :inverse() is the way to make a CFrame “negative”, and multiplying is the way CFrames add to each other.

So in a sense, they are taking the current CFrame and subtracting the previous CFrame from it to find the amount of position and rotation that changed during the loop. This change is called Rel. And the last line uses Rel to move the player to the Relative spot it was last loop; relative to the train car.


Now, the specifics of implementation, I don’t know, but I’m pretty sure it happens client-side based on some hints that @badcc was giving. Supposedly, Jailbreak’s implementation relies on network ownership to update the player positions between players which stutters based on connection due to the unusual nature of the movement, and Tyridge’s implementation sends the relative position to all players outright for smoother-looking movement. Also unknown is whether or not the update is occurring in RenderStepped, Heartbeat, or Stepped. All three are usable, as the load of the script is very small so there won’t be any concern about delaying render when using RenderStepped.


Ahh makes sense, thanks for explaining it in further depth, I’ll give it an attempt let you guys know how it turns out, may give it to you guys if you would like it.


This is my code, however it wont cframe as a local script doesn’t seem to be able to do that.


you need to set LastTrainCFrame after you calculate Rel. Otherwise you’re calculating the difference between something and itself (which is zero). You also need to break out LastTrainCFrame out of the loop either as an upvalue or as a global. And maybe what you have for finding the humanoid works in Play Solo, but you’ll have to move to Player.CharacterAdded event to get the current humanoid in a live game.



local Players = game:GetService("Players")

local LastTrainCF

local function onCharacterAdded(player)

while true do


--------------------------------------------------------------- CHECK PLATFORM BELLOW

local RootPart = player.HumanoidRootPart

local Ignore = player

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

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

if Hit.Name == "InertiaPart" then

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

local Train = Hit

local TrainCF = Train.CFrame

LastTrainCF = Hit.CFrame

local Rel = TrainCF * LastTrainCF:Inverse()

RootPart.CFrame = Rel * RootPart.CFrame




--------------------------------------------------------------- CONNECTED

local function onPlayerAdded(player)





Thanks for the heads up, though i have no idea on what i’m doing wrong?


Are you getting any errors?


No, however it seems to just keep me in the same position.


It would be nice if you posted your code in a code block. Formatting your code makes it easier for anyone to read your code and potentially help you with your problem.

Format a code block like so:

– Your code here

That’ll become

-- Your code here

Fixed, thanks for the tip, never new that it excised.


I tried this method. It does, indeed move my character. But not as intended, as you can see here.


Yeah exactly what im having issues with.


Switched it to server, it keeps ur character in the same position, and once you walk it moves it back.


I’m confused. Is this done on the client or server?


Both for replicating others

Client for preserving velocity to stay on the train


So your client is setting your character as fast as possible.

How about other client’s characters? How are they setted?