Hi,
I’m looking for some feedback on a basic instance replicator I made in a few minutes. It’s very bare-bones but does what is expected. The issue I was experiencing was that many instances (parts, folders, models, textures…) were parented to workspace when the player first joined. Obviously this caused performance issues for users with devices that had 1GB of ram, particularly crashing.
(Also thanks to Colbert for the example which this was based on)
Server script:
local players = game:GetService('Players')
local serverStorage = game:GetService('ServerStorage')
local replicatedStorage = game:GetService('ReplicatedStorage')
local playerData = replicatedStorage:WaitForChild('PlayerData')
local decorations = workspace:WaitForChild('Decorations')
decorations.Parent = serverStorage
local replicatedInstances = {} -- table that handles all instances that were replicated
local function handlePlayerAdded(player: Player)
local data = playerData:WaitForChild(player.UserId)
local settings = data:WaitForChild('Settings')
local stageDecorations = settings:WaitForChild('StageDecorations') -- this disables stage decorations, the instances that are being replicated
local playerGui = player:WaitForChild('PlayerGui') :: typeof(game:GetService('StarterGui'))
local instanceReplicationFolder = playerGui:WaitForChild('InstanceReplicationContainer') -- a ScreenGui that the items are parented to since this is the only way to simulate targeted replication
replicatedInstances[player.UserId] = {} -- table that contains all replicated instances for this player
local doReplication = true -- used to halt instances that are being replicated if need be
local function replicate()
doReplication = true
for i,v in ipairs(decorations:GetChildren()) do
local thisInstance = v:Clone()
thisInstance.Parent = instanceReplicationFolder
if i % 50 == 0 then
task.wait(0.1)
end
table.insert(replicatedInstances[player.UserId], thisInstance)
if not doReplication then -- if the setting is set to false mid-load
return
end
end
end
local function unReplicate() -- remove the replicated instances
doReplication = false
for i,v in ipairs(replicatedInstances[player.UserId]) do
v:Destroy()
end
end
if stageDecorations.Value then -- only if they choose to replicate stage decorations
replicate()
end
stageDecorations:GetPropertyChangedSignal('Value'):Connect(function()
if stageDecorations.Value then -- is this if-statement necessary?
replicate()
else
unReplicate()
end
end)
end
for i,v in ipairs(players:GetPlayers()) do -- just in case
handlePlayerAdded(v)
end
players.PlayerAdded:Connect(handlePlayerAdded)
players.PlayerRemoving:Connect(function(player)
if replicatedInstances[player.UserId] then
for i,v in ipairs(replicatedInstances[player.UserId]) do
v:Destroy() -- destroy the instances
end
replicatedInstances[player.UserId] = nil -- discard the table
end
end)
LocalScript, child of instance replication folder:
script.Parent.ChildAdded:Connect(function(child)
if child ~= script then -- shouldn't ever fire but just in case
task.defer(function() -- need task.defer so it doesn't spam "something unexpectedly set the parent of ___"
child.Parent = workspace
end)
end
end)
That’s it.
I’m looking for ways to further improve performance if any. I also want to remove the task.defer if possible but I don’t know if it’s possible.
Thanks!