Best method to create a moving object that players can stand on?

In a game I’m working, there is a train car that moves around on a track and the player can jump on top of it.

The problem here is the way I traditionally move a part is by modifying the part’s CFrame or position in a loop, separated by wait().

This creates a pretty consistent, easy to plot movement, however the part moves with no respect for the player’s character. If you jump on top of my moving train car, you won’t move with it like real physics would dictate.

What would be the best way to get this working?
I am aware of a method that welds the character to the part, but this seems kind of hacky and if there is a cleaner solution I’d rather use that.

I am also aware of different physics objects like body movers, however in my experience these do not provide a consistent speed, you are very much at the mercy of their limitations and it doesn’t let you do a whole lot.

Any guidance on this topic would be appreciated. Thanks!

3 Likes

The best way to my knowledge is using something like

local weld = Instance.new("WeldConstraint")

and

weld:Destroy()

similar to what I posted here: How can I Make Two Parts Weld On Touch? - #2 by AlerbusWasTaken

I know you said you don’t want to weld, but it’s one of the best and simplest methods.

1 Like

I have tried implementing your method, and it leads to a weird result.

When I jump on the moving train car with my character, they do not stay stuck to the train car, just like before.

However, something odd happens when the train car moves away and the character would normally fall to their death. Instead, they go into their falling animation but just stay stuck floating there.
Capture

Any experience with this happening?

1 Like

Just do your usual cframe on part with tweenservice or renderstepped both on client then you can “attach” the character using a raycast and set the position reative to ontop of the part the player is on.

Heres the jist:

7 Likes

Works great! I needed to make a few modifications to get it running so I’ll just post that here for others to use. Throw this in a local script in StarterPlayerScripts and it should be good to go!

--Written by Kord_K. Slight modifications by BADGRAPHIX.

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

    local LastTrainCFrame

    local Function
    local Function2


    Function = RunService.Heartbeat:Connect(function()

    	--------------------------------------------------------------- CHECK PLATFORM BELOW
    	if player.Character then
    		local RootPart = player.Character:FindFirstChild("LowerTorso")
    		if RootPart then
    			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 Hit.Name == "TrainCarC" 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
    	end
    end)
4 Likes

You could also do the exact opposite and make the surroundings move instead of the train to give the illusion

That wouldn’t work with terrain, which is heavily used, and would cause severe lag moving the entire map.

2 Likes