Using the code below works, but I get the same result as method 4. Not knowing how long the wait() has to be. Since wait() is too fast. But wait(0.2) not. So there may be cases where wait(0.2) could not be fast enough
script.Parent:GetPropertyChangedSignal("Occupant"):Connect(function()
local Humanoid = script.Parent.Occupant
if not Humanoid then
return
end
connection = Humanoid.StateChanged:Connect(function(prevState, newState)
if prevState == Enum.HumanoidStateType.Seated then
Humanoid.Parent.HumanoidRootPart.CFrame = CFrame.new(0, 10, 0)
connection:Disconnect()
end
end)
end)
I have been battling with this issue for a while - is hard to solve since it is hard to reproduce and since Seats are kind of odd fellows. Seats got teleported for players in production, but not when developing in Studio (or team test).
Tried to listen to different property changes that the player is no longer seated, arbitrary waits, run unseat on the client before server teleported the player, unseat the player on the server etc without any results.
The solution I settled on was the dirty hack of teleporting the seat back to the original position if it got teleported with the player:
local humanoid = player.Character:FindFirstChild("Humanoid")
if humanoid then
if humanoid.SeatPart then
-- Delay a restore original seat position...
local seatPart = humanoid.SeatPart
local originalSeatCFrame = seatPart.CFrame
delay(4, function()
seatPart.CFrame = originalSeatCFrame
end)
-- Do a futile attempt to unseat the player
humanoid.SeatPart:Sit(nil)
humanoid.Sit = false
humanoid:GetPropertyChangedSignal("SeatPart"):Wait()
end
end
player.Character.HumanoidRootPart.CFrame = targetPosition
Might not fall under “properly”, but was the solution I ended up with. There might be some better solution where the server syncs with the client so both agree on the player being unseated using remote events, but I have spent enough time on this as it is.
I ran into this problem earlier today when attempting to teleport players out of seats. I couldn’t find a reliable way to ensure seats didn’t get teleported with the player.
Thanks to Sam’s solution above, I can get around the problem. However it’s disappointing I couldn’t find a normal way to guarantee that the seat doesn’t get teleported too. Shouldn’t there be a better way to solve this problem?
One way to do can be just by disabling the seat for a while and then teleporting the player
local Char = Player.Character
local Hum = Char.Humanoid
local Seat = Hum.SeatPart --Locating the Seat
Seat.Disable = true --Disables the Seat
Hum.Sit = false --Making it Stand
Char:SetPrimaryPartCFrame(game.Workspace.Part.Postion) --Since Character is a Model and has a Humanoid it will work good
Seat.Disable = false -- If you want to \_(O.O)_/
While your code is mostly correct, there needs to be a small wait time or else it will try to teleport the player too fast. I’ve corrected this in the code below:
seat.Disabled = true -- Will make the player unable to sit in the seat so they don't accidentally sit back in it before teleporting
Humanoid.Sit = false -- This will make the player stand up from the seat
repeat wait() -- this will wait until the player is no longer sitting
until Humanoid.Sit == false
wait(.1) -- I haven't tested this code without this wait, but I like having precautions
Character.HumanoidRootPart.CFrame = CFrame.new(workspace.part.position) -- This is the teleport code
seat.Disabled = false -- Allows the seat to be used again
for _,v in pairs(workspace:GetDescendants()) do
if v:IsA("Seat") then
local originalpos = v.CFrame
v:GetPropertyChangedSignal("Occupant"):Connect(function()
if v.Occupant == nil then
v.CFrame = originalpos
else
wait()
local Occupant = v.Occupant.Parent
local HRP = Occupant.HumanoidRootPart
local OccOrigPos = HRP.Position
while wait(.1) do
local OccCurrentPos = HRP.Position
if (OccCurrentPos - OccOrigPos).magnitude > 10 then
if v:FindFirstChild("SeatWeld") then
v.SeatWeld:Destroy()
end
end
end
end
end)
end
end
If you want to be indiscriminate, this doubly protects by retaining the original position of the seat and unseating the player when they teleport. Can be placed in any server script.
In 2024, I’m successfully teleporting characters by simply cloning and destroying the seat part:
local humanoid = player.Character.Humanoid
local seat = humanoid.SeatPart
if seat then
humanoid.Sit = false
local seatParent = seat.Parent
local seatCopy = seat:Clone()
task.defer(function()
RunService.Heartbeat:Wait()
pcall(seat.Destroy, seat)
seatCopy.Parent = seatParent
end)
end
player.Character:PivotTo(newLocation)
The year is 2025, and I have found the solution, works 100% of the time (for me), and I am able to teleport the player between seats without having to rely on task.wait, wait, any events or whatsoever.
Here is the code for those in the future looking for it:
Humanoid.Seated = false -- makes him stand up from the seat
Seat:Sit(Humanoid) -- Seat is the seat you want the player to be in
for everyone here dont use the above solutions cause some of them only work on the server and break on the client and some dont work at all & work but break the seat which caused problems for my game
this is the best solution ive found after testing you can put it in a module script
if you dont like the loop replace it with a task.wait(0.1) no lower but i found the loop to be slightly faster and game conditions are slower than studio so the loop is more reliable ig
local module = {}
local function breakSeat(char :Model)
local humanoid = char:FindFirstChildOfClass("Humanoid")
if humanoid then
if humanoid.SeatPart then
humanoid.Sit = false
repeat task.wait() until not humanoid.SeatPart
end
end
end
function module.PivotTo(char :Model, cframe :CFrame)
breakSeat(char)
char:PivotTo(cframe)
end
function module.MoveTo(char :Model, vector3 :Vector3)
breakSeat(char)
char:MoveTo(vector3)
end
return module
test file: F to teleport from client / K to teleport from server test.rbxl (59.9 KB)
Have you guys tried firing a remote event to the client to unseat and teleport themselves? Since the client has network ownership over their character this should be working.