Moving parts with Tween Service does NOT move the player physically

Hello everyone.

I have a problem with using tween service to move other parts physically.

I used Tween Service to move a train model so it can move players from a station to another (look in “Example 1”), but I realize that once a player jumps off of the seat or just don’t use the seat at all, the tween will ignore the fraction between the player and the floor (look in “Example 2”)

I’m trying to make the player move with the train, as 1 part, (look in “Example 3”)

Example 1

Example 2

Example 3

1 solution I thought of doing, is to weld the player to the floor, so the player doesn’t fly off of the train, however, it takes time to set up, and it doesn’t allow the player to move freely inside the train.

This is the script that I’m using, not sure how its gonna help but it’s here just in case:

  tweenService = game:GetService("TweenService")
---------------------------------------------------------- START

  Model = script.Parent
  goal1 = script.Parent.Parent.Station1

  origCFrame1 = Model.PrimaryPart.CFrame


  tweenTime = 5
  closeWaitTime = 0
  easingStyle = Enum.EasingStyle.Sine
  easingDirection = Enum.EasingDirection.InOut
  repeats = 0
  reverse = false
  delayTime = 0


  deb = false
  info = TweenInfo.new(tweenTime, easingStyle, easingDirection, repeats, reverse, delayTime)
  function tweenModel(model, CF)
      CFrameValue = Instance.new("CFrameValue")
    CFrameValue.Value = model:GetPrimaryPartCFrame()

    CFrameValue:GetPropertyChangedSignal("Value"):Connect(function()
        model:SetPrimaryPartCFrame(CFrameValue.Value)
    end)
    
      tween = tweenService:Create(CFrameValue, info, {Value = CF})
    tween:Play()
    
    tween.Completed:Connect(function()
        CFrameValue:Destroy()
    end)
end
wait(0)
tweenModel(Model, goal1.CFrame)

wait(5)

--------------------------SETP1
script.Parent.Elevator.Sound.PLAY.Disabled = false

  Model = script.Parent
  goal1 = script.Parent.Parent.TScanner2

  origCFrame1 = Model.PrimaryPart.CFrame


  tweenTime = 5
  closeWaitTime = 0
  easingStyle = Enum.EasingStyle.Sine
  easingDirection = Enum.EasingDirection.InOut
  repeats = 0
  reverse = false
  delayTime = 0


  deb = false
  info = TweenInfo.new(tweenTime, easingStyle, easingDirection, repeats, reverse, delayTime)
  function tweenModel(model, CF)
	  CFrameValue = Instance.new("CFrameValue")
	CFrameValue.Value = model:GetPrimaryPartCFrame()
	
	CFrameValue:GetPropertyChangedSignal("Value"):Connect(function()
		model:SetPrimaryPartCFrame(CFrameValue.Value)
	end)
	
	  tween = tweenService:Create(CFrameValue, info, {Value = CF})
	tween:Play()
	
	tween.Completed:Connect(function()
		CFrameValue:Destroy()
	end)
end
wait(0)
tweenModel(Model, goal1.CFrame)

wait(5)
script.Parent.Elevator.Sound.STOP.Disabled = false
--------------------------SETP2
wait(1)
game.Workspace.Scanner2.Door.ScannerTween.Disabled = false
wait(6)
----------------------------------------------------------
script.Parent.Elevator.Sound.PLAY.Disabled = false

  Model = script.Parent
  goal1 = script.Parent.Parent.Station1

  origCFrame1 = Model.PrimaryPart.CFrame


  tweenTime = 5
  closeWaitTime = 0
  easingStyle = Enum.EasingStyle.Sine
  easingDirection = Enum.EasingDirection.InOut
  repeats = 0
  reverse = false
  delayTime = 0


  deb = false
  info = TweenInfo.new(tweenTime, easingStyle, easingDirection, repeats, reverse, delayTime)
  function tweenModel(model, CF)
	  CFrameValue = Instance.new("CFrameValue")
	CFrameValue.Value = model:GetPrimaryPartCFrame()
	
	CFrameValue:GetPropertyChangedSignal("Value"):Connect(function()
		model:SetPrimaryPartCFrame(CFrameValue.Value)
	end)
	
	  tween = tweenService:Create(CFrameValue, info, {Value = CF})
	tween:Play()
	
	tween.Completed:Connect(function()
		CFrameValue:Destroy()
	end)
end
wait(0)
tweenModel(Model, goal1.CFrame)

wait(5)
script.Parent.Elevator.Sound.STOP.Disabled = false
wait(1)
script.Parent.MoonTrain.TrainDoors.ActiveDoorsR.Disabled = false
wait(20)
--------------------------SETP3
script.Parent.Elevator.Sound.PLAY.Disabled = false

  Model = script.Parent
  goal1 = script.Parent.Parent.TScanner1

  origCFrame1 = Model.PrimaryPart.CFrame


  tweenTime = 5
  closeWaitTime = 0
  easingStyle = Enum.EasingStyle.Sine
  easingDirection = Enum.EasingDirection.InOut
  repeats = 0
  reverse = false
  delayTime = 0


  deb = false
  info = TweenInfo.new(tweenTime, easingStyle, easingDirection, repeats, reverse, delayTime)
  function tweenModel(model, CF)
	  CFrameValue = Instance.new("CFrameValue")
	CFrameValue.Value = model:GetPrimaryPartCFrame()
	
	CFrameValue:GetPropertyChangedSignal("Value"):Connect(function()
		model:SetPrimaryPartCFrame(CFrameValue.Value)
	end)
	
	  tween = tweenService:Create(CFrameValue, info, {Value = CF})
	tween:Play()
	
	tween.Completed:Connect(function()
		CFrameValue:Destroy()
	end)
end
wait(0)
tweenModel(Model, goal1.CFrame)

wait(5)
script.Parent.Elevator.Sound.STOP.Disabled = false
--------------------------SETP3.5
wait(1)
game.Workspace.Scanner1.Door.ScannerTween.Disabled = false
wait(6)

script.Disabled = true
script.Disabled = false

Please, if you have any idea about a solution, then please don’t hesitate to tell me about it.
Thank You.

If you put this script inside the StarterCharacterScripts in a localscript it should fix your issue.
Just remember to have an invisible part at the bottom of each train cart named “TrainFloor”

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

local LastTrainCFrame

local Function
local Function2

local TRAIN_BASE_NAME = "TrainFloor"

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 Hit.Name == TRAIN_BASE_NAME then 
		-- 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
	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)

for example if this was your train:

the red transparent part is what you’d name “TrainFloor”:

the script uses raycasting to detect if you’re on top of train floor and if you are it cframes relatively to the red part (train floor).

18 Likes

That WORKS perfectly! I have read so many threads to find this! Thanks!

2 Likes

Hey! It does work great, but when I walk directly onto another TrainFloor (for a multi-car train) it teleports me to the other end of the platform.
Do you have any idea how I could stop this from happening?

An alternative I’ve thought of is I can script a system with proximity prompts that players need to use to cross between cars, but it kind of removes the experience of passing between cars, any ideas?

2 Likes

Hey, I came here looking for the same solution as you, but I noticed you able to make the trains turn with tweenService so smoothly. How were you able to do it? Im not asking for any code, just asking how you overall did it.

If you dont feel like sharing it, I totally understand

OH and for those wondering why this isnt working for you all, 1 OF the reasons is because the avatar is R6