So I had been experiencing this issue and my initial decision was to separate the functional elevator and the visual elevator into client/server. The visual elevator is client based and applies to all clients but is rendered by each player, but physical movement is server based so multiple players can ride the same elevator. This solved the problem of the player shaking and falling because now the invisible physical elevator doesn’t shake. The problem I’m now facing is the VISUAL elevator, the one with collisions off, is shaking while it moves. This is, as I understand it, a very common problem with roblox elevators but I was assuming that combining most of the small parts into a mesh would solve the rendering problem, but it did not. I will provide the scripts here so you can see the relation of the client and server scripts, and I’ve labeled the sections for visibility.
Server Script:
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
---------------------------------------------------
-- REMOTE EVENT
---------------------------------------------------
local moveEvent =
ReplicatedStorage:WaitForChild(
"ServiceLift2_MoveEvent"
)
---------------------------------------------------
-- SERVER ELEVATOR
---------------------------------------------------
local elevator =
workspace:WaitForChild(
"ServiceElevator2_Server"
)
---------------------------------------------------
-- ROOT PART
---------------------------------------------------
local rootPart =
elevator:WaitForChild(
"RootPart"
)
elevator.PrimaryPart = rootPart
---------------------------------------------------
-- FLOOR POSITIONS
---------------------------------------------------
local floor1Pos =
workspace:WaitForChild(
"ServiceElevator2FloorPosition1"
)
local floor2Pos =
workspace:WaitForChild(
"ServiceElevator2FloorPosition2"
)
---------------------------------------------------
-- BUTTONS
---------------------------------------------------
local floor1Button =
elevator:WaitForChild(
"FloorOneButton"
).ClickDetector
local floor2Button =
elevator:WaitForChild(
"FloorTwoButton"
).ClickDetector
---------------------------------------------------
-- FLOOR 1 CALL BUTTON
---------------------------------------------------
local callButton =
workspace:WaitForChild(
"CallButtonServiceElevator2"
).ClickDetector
---------------------------------------------------
-- FLOOR 2 CALL BUTTON
---------------------------------------------------
local callButton2 =
workspace:WaitForChild(
"CallButton2ServiceElevator2"
).ClickDetector
---------------------------------------------------
-- SERVER DOORS
---------------------------------------------------
local insideLeft =
elevator:WaitForChild(
"InsideDoorLeft"
)
local insideRight =
elevator:WaitForChild(
"InsideDoorRight"
)
---------------------------------------------------
-- SETTINGS
---------------------------------------------------
local MOVE_TIME = 20
local DOOR_TIME = 1.5
local moving = false
local currentFloor = 1
---------------------------------------------------
-- SAVE OPEN POSITIONS
---------------------------------------------------
local insideLeftOpen =
insideLeft:GetPivot()
local insideRightOpen =
insideRight:GetPivot()
---------------------------------------------------
-- CLOSED POSITIONS
---------------------------------------------------
local insideLeftClosed =
insideLeftOpen
* CFrame.Angles(0, math.rad(90), 0)
local insideRightClosed =
insideRightOpen
* CFrame.Angles(0, math.rad(-90), 0)
---------------------------------------------------
-- DOOR TWEEN
---------------------------------------------------
local function tweenDoor(
model,
targetCF
)
local value =
Instance.new("CFrameValue")
value.Value =
model:GetPivot()
local connection =
value:GetPropertyChangedSignal(
"Value"
):Connect(function()
model:PivotTo(
value.Value
)
end)
local tween = TweenService:Create(
value,
TweenInfo.new(
DOOR_TIME,
Enum.EasingStyle.Sine,
Enum.EasingDirection.InOut
),
{
Value = targetCF
}
)
tween:Play()
tween.Completed:Wait()
connection:Disconnect()
value:Destroy()
end
---------------------------------------------------
-- OPEN DOORS
---------------------------------------------------
local function openDoors()
task.spawn(function()
tweenDoor(
insideLeft,
insideLeftOpen
)
end)
task.spawn(function()
tweenDoor(
insideRight,
insideRightOpen
)
end)
end
---------------------------------------------------
-- CLOSE DOORS
---------------------------------------------------
local function closeDoors()
task.spawn(function()
tweenDoor(
insideLeft,
insideLeftClosed
)
end)
task.spawn(function()
tweenDoor(
insideRight,
insideRightClosed
)
end)
wait(DOOR_TIME)
end
---------------------------------------------------
-- MOVE ELEVATOR
---------------------------------------------------
local function moveElevator(
targetPart,
targetFloor
)
if moving then
return
end
moving = true
------------------------------------------------
-- CLOSE SERVER DOORS
------------------------------------------------
closeDoors()
------------------------------------------------
-- SAVE START POSITION
------------------------------------------------
local startCF =
rootPart.CFrame
------------------------------------------------
-- TELL CLIENTS TO CLOSE DOORS
------------------------------------------------
moveEvent:FireAllClients(
"CloseDoors"
)
------------------------------------------------
-- WAIT FOR CLIENT DOORS
------------------------------------------------
wait(DOOR_TIME)
------------------------------------------------
-- MOVE REAL ELEVATOR
------------------------------------------------
local value =
Instance.new("CFrameValue")
value.Value =
startCF
local connection =
value:GetPropertyChangedSignal(
"Value"
):Connect(function()
elevator:PivotTo(
value.Value
)
end)
local tween = TweenService:Create(
value,
TweenInfo.new(
MOVE_TIME,
Enum.EasingStyle.Sine,
Enum.EasingDirection.InOut
),
{
Value = targetPart.CFrame
}
)
------------------------------------------------
-- START CLIENT MIRRORING
------------------------------------------------
moveEvent:FireAllClients(
"MoveElevator",
startCF,
targetPart.CFrame,
MOVE_TIME,
targetFloor
)
------------------------------------------------
-- WAIT ONE FRAME
------------------------------------------------
task.wait()
------------------------------------------------
-- START SERVER MOVEMENT
------------------------------------------------
tween:Play()
------------------------------------------------
-- WAIT FOR COMPLETION
------------------------------------------------
tween.Completed:Wait()
connection:Disconnect()
value:Destroy()
currentFloor = targetFloor
wait(0.5)
------------------------------------------------
-- OPEN SERVER DOORS
------------------------------------------------
openDoors()
------------------------------------------------
-- TELL CLIENTS TO OPEN DOORS
------------------------------------------------
moveEvent:FireAllClients(
"OpenDoors",
nil,
nil,
nil,
targetFloor
)
moving = false
end
---------------------------------------------------
-- INSIDE BUTTONS
---------------------------------------------------
floor2Button.MouseClick:Connect(function()
if currentFloor == 1 then
moveElevator(
floor2Pos,
2
)
end
end)
floor1Button.MouseClick:Connect(function()
if currentFloor == 2 then
moveElevator(
floor1Pos,
1
)
end
end)
---------------------------------------------------
-- FLOOR 1 CALL BUTTON
---------------------------------------------------
callButton.MouseClick:Connect(function()
if currentFloor == 2 then
moveElevator(
floor1Pos,
1
)
end
end)
---------------------------------------------------
-- FLOOR 2 CALL BUTTON
---------------------------------------------------
callButton2.MouseClick:Connect(function()
if currentFloor == 1 then
moveElevator(
floor2Pos,
2
)
end
end)
---------------------------------------------------
-- START OPEN
---------------------------------------------------
insideLeft:PivotTo(
insideLeftOpen
)
insideRight:PivotTo(
insideRightOpen
)
ClientScript:
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
---------------------------------------------------
-- REMOTE EVENT
---------------------------------------------------
local moveEvent =
ReplicatedStorage:WaitForChild(
"ServiceLift2_MoveEvent"
)
---------------------------------------------------
-- VISUAL ELEVATOR
---------------------------------------------------
local elevator =
workspace:WaitForChild(
"ServiceElevator2_Visual"
)
---------------------------------------------------
-- SERVER ELEVATOR
---------------------------------------------------
local serverElevator =
workspace:WaitForChild(
"ServiceElevator2_Server"
)
---------------------------------------------------
-- ROOT PARTS
---------------------------------------------------
local visualRoot =
elevator:WaitForChild(
"RootPart"
)
local serverRoot =
serverElevator:WaitForChild(
"RootPart"
)
elevator.PrimaryPart =
visualRoot
serverElevator.PrimaryPart =
serverRoot
---------------------------------------------------
-- VISUAL DOORS
---------------------------------------------------
local insideLeft =
elevator:WaitForChild(
"InsideDoorLeft"
)
local insideRight =
elevator:WaitForChild(
"InsideDoorRight"
)
---------------------------------------------------
-- OUTSIDE DOORS
---------------------------------------------------
local outsideLeft =
workspace:WaitForChild(
"ServiceElevator2OutsideDoorLeft"
)
local outsideRight =
workspace:WaitForChild(
"ServiceElevator2OutsideDoorRight"
)
---------------------------------------------------
-- SETTINGS
---------------------------------------------------
local DOOR_TIME = 1.5
---------------------------------------------------
-- RELATIVE INSIDE DOOR OFFSETS
---------------------------------------------------
local insideLeftOpenOffset =
elevator.PrimaryPart.CFrame:ToObjectSpace(
insideLeft:GetPivot()
)
local insideRightOpenOffset =
elevator.PrimaryPart.CFrame:ToObjectSpace(
insideRight:GetPivot()
)
local insideLeftClosedOffset =
insideLeftOpenOffset
* CFrame.Angles(0, math.rad(90), 0)
local insideRightClosedOffset =
insideRightOpenOffset
* CFrame.Angles(0, math.rad(-90), 0)
---------------------------------------------------
-- OUTSIDE DOOR POSITIONS
---------------------------------------------------
local outsideLeftOpen =
outsideLeft:GetPivot()
local outsideRightOpen =
outsideRight:GetPivot()
local outsideLeftClosed =
outsideLeftOpen
* CFrame.Angles(0, math.rad(-90), 0)
local outsideRightClosed =
outsideRightOpen
* CFrame.Angles(0, math.rad(90), 0)
---------------------------------------------------
-- GET INSIDE DOOR POSITIONS
---------------------------------------------------
local function getInsideLeftOpen()
return elevator.PrimaryPart.CFrame
* insideLeftOpenOffset
end
local function getInsideRightOpen()
return elevator.PrimaryPart.CFrame
* insideRightOpenOffset
end
local function getInsideLeftClosed()
return elevator.PrimaryPart.CFrame
* insideLeftClosedOffset
end
local function getInsideRightClosed()
return elevator.PrimaryPart.CFrame
* insideRightClosedOffset
end
---------------------------------------------------
-- DOOR TWEEN
---------------------------------------------------
local function tweenDoor(
model,
targetCF
)
local value =
Instance.new("CFrameValue")
value.Value =
model:GetPivot()
local connection =
value:GetPropertyChangedSignal(
"Value"
):Connect(function()
model:PivotTo(
value.Value
)
end)
local tween = TweenService:Create(
value,
TweenInfo.new(
DOOR_TIME,
Enum.EasingStyle.Sine,
Enum.EasingDirection.InOut
),
{
Value = targetCF
}
)
tween:Play()
tween.Completed:Wait()
connection:Disconnect()
value:Destroy()
end
---------------------------------------------------
-- OPEN DOORS
---------------------------------------------------
local function openDoors(
targetFloor
)
task.spawn(function()
tweenDoor(
insideLeft,
getInsideLeftOpen()
)
end)
task.spawn(function()
tweenDoor(
insideRight,
getInsideRightOpen()
)
end)
if targetFloor == 1 then
task.spawn(function()
tweenDoor(
outsideLeft,
outsideLeftOpen
)
end)
task.spawn(function()
tweenDoor(
outsideRight,
outsideRightOpen
)
end)
end
end
---------------------------------------------------
-- CLOSE DOORS
---------------------------------------------------
local function closeDoors()
task.spawn(function()
tweenDoor(
insideLeft,
getInsideLeftClosed()
)
end)
task.spawn(function()
tweenDoor(
insideRight,
getInsideRightClosed()
)
end)
task.spawn(function()
tweenDoor(
outsideLeft,
outsideLeftClosed
)
end)
task.spawn(function()
tweenDoor(
outsideRight,
outsideRightClosed
)
end)
end
---------------------------------------------------
-- RECEIVE EVENTS
---------------------------------------------------
moveEvent.OnClientEvent:Connect(function(
action,
startCF,
endCF,
moveTime,
targetFloor
)
if action == "CloseDoors" then
closeDoors()
end
if action == "MoveElevator" then
local renderConnection
renderConnection =
RunService.RenderStepped:Connect(function()
elevator:PivotTo(
serverElevator:GetPivot()
)
end)
task.wait(moveTime)
renderConnection:Disconnect()
local offset =
elevator.PrimaryPart.CFrame:Inverse()
* elevator:GetPivot()
elevator:PivotTo(
serverRoot.CFrame * offset
)
end
if action == "OpenDoors" then
openDoors(targetFloor)
end
end)