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)