You have an extreme amount of connections you are not disconnecting. This is most likely causing huge memory leaks which will affect your game greatly. I disconnected all connections you aren’t using for you, but I’m not sure if it works until you test it.
Code:
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local client = require(game.StarterPlayer.StarterPlayerScripts:WaitForChild("Client"))
local ViewportModel = require(game.ReplicatedStorage.ViewportModel)
local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local placementEvent = game.ReplicatedStorage.RemoteEvents.PlacementEvent
local objFolder = game.ReplicatedStorage:WaitForChild("ObjectFolder")
local mouse = player:GetMouse()
local Frame = player.PlayerGui.ScreenGui.Building.ScrollingFrame
local itemPopup = player.PlayerGui.ScreenGui.BuildingItemPopup
local placingObject = false
local rotatingObject = false
local function DisplayStructures()
for _, v in pairs(workspace.Plots[player.Name].Structures:GetChildren()) do
local highlight = Instance.new("Highlight", v)
highlight.OutlineColor = Color3.new(0.741176, 0.741176, 0.741176)
highlight.FillColor = Color3.new(1, 1, 1)
task.spawn(function()
while task.wait(0.5) do
local highlightTween = game:GetService("TweenService"):Create(highlight, TweenInfo.new(0.5), {FillColor = Color3.new(1, 1, 1)})
highlightTween:Play()
highlightTween.Completed:Wait()
game:GetService("TweenService"):Create(highlight, TweenInfo.new(0.5), {FillColor = Color3.new(0.784314, 0.784314, 0.784314)}):Play()
end
end)
end
end
local function DisableStructures()
for _, v in pairs(game.Workspace.Plots[player.Name].Structures:GetDescendants()) do
if v:IsA("Highlight") then
v:Destroy()
end
end
end
local function isInsidePlot(position, plotPart)
local plotSize = plotPart.Size / 2
local plotCFrame = plotPart.CFrame
local plotMin = plotCFrame.Position - plotSize
local plotMax = plotCFrame.Position + plotSize
return position.X >= plotMin.X and position.X <= plotMax.X
and position.Z >= plotMin.Z and position.Z <= plotMax.Z
end
--Placement
local function EnablePlacement()
for _, buttonFrame in pairs(Frame:GetChildren()) do
if buttonFrame:IsA("Frame") then
local button:ImageButton = buttonFrame.Button
local connections = {}
local nestedConnections = {}
button.MouseButton1Click:Connect(function()
for i, connection in connections do
connection:Disconnect()
end
table.clear(connections)
for i, connection in nestedConnections do
connection:Disconnect()
end
table.clear(nestedConnections)
itemPopup.Visible = true
client.OpenUI(player.PlayerGui.ScreenGui.Building)
DisableStructures()
local object = game.ReplicatedStorage.ObjectFolder[buttonFrame.Name]
itemPopup.ObjectName.Text = buttonFrame.Name
itemPopup.Price.Text = buttonFrame.Cost.Text
itemPopup.Desc.Text = object:GetAttribute("Desc")
local camClone = object:Clone()
local camera = Instance.new("Camera")
camera.FieldOfView = 70
camera.Parent = itemPopup.ViewportFrame
camClone.Parent = itemPopup.ViewportFrame
itemPopup.ViewportFrame.CurrentCamera = camera
local vpfModel = ViewportModel.new(itemPopup.ViewportFrame, camera)
local cf, size = camClone:GetBoundingBox()
vpfModel:SetModel(camClone)
local theta = 0
local orientation = CFrame.new()
local distance = vpfModel:GetFitDistance(cf.Position)
table.insert(connections, game:GetService("RunService").RenderStepped:Connect(function(dt)
theta = theta + math.rad(20 * dt)
orientation = CFrame.fromEulerAnglesYXZ(math.rad(-20), theta, 0)
camera.CFrame = CFrame.new(cf.Position) * orientation * CFrame.new(0, 0, distance)
end))
table.insert(connections, itemPopup.Place.MouseButton1Click:Connect(function()
for i, connection in nestedConnections do
connection:Disconnect()
end
table.clear(nestedConnections)
camClone:Destroy()
camera:Destroy()
itemPopup.Visible = false
if not placingObject then
for _, sideButton in pairs(player.PlayerGui.ScreenGui.MainButtons:GetChildren()) do
sideButton.Visible = false
end
for _, sideButton in pairs(player.PlayerGui.ScreenGui.BuildingToolTips:GetChildren()) do
sideButton.Visible = true
end
placingObject = true
local rotationAmount = 0
local gridSnapping = 0.5
local previewObject = objFolder:FindFirstChild(buttonFrame.Name):Clone()
previewObject.Parent = workspace
for _, part in pairs(previewObject:GetDescendants()) do
if part:IsA("BasePart") then
part.Transparency = 0.5
part.CanCollide = false
end
if part:IsA("ProximityPrompt") then
part.Enabled = false
end
end
table.insert(nestedConnections, UserInputService.InputBegan:Connect(function(key, gp)
if not gp then
if key.KeyCode == Enum.KeyCode.R then
rotatingObject = true
rotationAmount += 90
game.SoundService.GridSnap:Play()
end
if key.KeyCode == Enum.KeyCode.X then
if placingObject then
rotatingObject = false
placingObject = false
previewObject:Destroy()
client.OpenUI(player.PlayerGui.ScreenGui.Building)
DisplayStructures()
game.SoundService.CancelPlacement:Play()
for _, sideButton in pairs(player.PlayerGui.ScreenGui.MainButtons:GetChildren()) do
sideButton.Visible = true
end
for _, sideButton in pairs(player.PlayerGui.ScreenGui.BuildingToolTips:GetChildren()) do
sideButton.Visible = false
end
end
end
end
end))
table.insert(nestedConnections, UserInputService.InputEnded:Connect(function(key, gp)
if key.KeyCode == Enum.KeyCode.R then
rotatingObject = false
end
end))
table.insert(nestedConnections, RunService.RenderStepped:Connect(function(deltaTime)
if placingObject then
mouse.TargetFilter = previewObject
if previewObject:FindFirstChild("MainPart") then
local ObjectCFrame = CFrame.new(math.round(mouse.hit.Position.X/gridSnapping)*gridSnapping, mouse.hit.Position.Y + previewObject.PrimaryPart.Size.Y/2, math.round(mouse.hit.Position.Z/gridSnapping)*gridSnapping)
local ObjectAngles = CFrame.Angles(0,math.rad(rotationAmount), 0)
if isInsidePlot(mouse.Hit.Position, game.Workspace.Plots[player.Name].PlotPart) then
previewObject:SetPrimaryPartCFrame(ObjectCFrame * ObjectAngles)
end
end
end
end))
table.insert(nestedConnections, mouse.Button1Up:Connect(function()
if placingObject then
if player.leaderstats.Cash.Value >= objFolder[buttonFrame.Name]:GetAttribute("Price") then
placingObject = false
game.SoundService.HammerAndNail:Play()
for _, sideButton in pairs(player.PlayerGui.ScreenGui.MainButtons:GetChildren()) do
sideButton.Visible = true
end
for _, sideButton in pairs(player.PlayerGui.ScreenGui.BuildingToolTips:GetChildren()) do
sideButton.Visible = false
end
placementEvent:FireServer(previewObject.Name, previewObject.PrimaryPart.CFrame)
client.OpenUI(player.PlayerGui.ScreenGui.Building)
DisplayStructures()
previewObject:Destroy()
else
client.OpenUI(player.PlayerGui.ScreenGui.Building)
DisplayStructures()
previewObject:Destroy()
placingObject = false
for _, sideButton in pairs(player.PlayerGui.ScreenGui.MainButtons:GetChildren()) do
sideButton.Visible = true
end
for _, sideButton in pairs(player.PlayerGui.ScreenGui.BuildingToolTips:GetChildren()) do
sideButton.Visible = false
end
end
end
end))
end
end))
table.insert(connections, itemPopup.Cancel.MouseButton1Click:Connect(function()
client.OpenUI(player.PlayerGui.ScreenGui.Building)
camClone:Destroy()
camera:Destroy()
itemPopup.Visible = false
DisplayStructures()
end))
end)
end
end
end
for _, object in pairs(game.ReplicatedStorage.ObjectFolder:GetChildren()) do
local uiButton = game.ReplicatedStorage.BuildingItem:Clone()
uiButton.Parent = player.PlayerGui.ScreenGui.Building.ScrollingFrame
uiButton.ItemName.Text = object.Name
uiButton.Cost.Text = "$"..tostring(object:GetAttribute("Price"))
uiButton.Name = object.Name
local camClone = object:Clone()
local camera = Instance.new("Camera")
camera.FieldOfView = 70
camera.Parent = uiButton.ViewportFrame
camClone.Parent = uiButton.ViewportFrame
uiButton.ViewportFrame.CurrentCamera = camera
local vpfModel = ViewportModel.new(uiButton.ViewportFrame, camera)
local cf, size = camClone:GetBoundingBox()
vpfModel:SetModel(camClone)
local theta = 0
local orientation = CFrame.new()
local distance = vpfModel:GetFitDistance(cf.Position)
game:GetService("RunService").RenderStepped:Connect(function(dt)
theta = theta + math.rad(20 * dt)
orientation = CFrame.fromEulerAnglesYXZ(math.rad(-20), theta, 0)
camera.CFrame = CFrame.new(cf.Position) * orientation * CFrame.new(0, 0, distance)
end)
EnablePlacement()
end
for _, button in pairs(player.PlayerGui.ScreenGui.Building.Frame:GetChildren()) do
if button:IsA("TextButton") then
local displayConnections = {}
--Display Buttons
button.MouseButton1Click:Connect(function()
game.SoundService.OpenUI:Play()
for _, frame in pairs(player.PlayerGui.ScreenGui.Building.ScrollingFrame:GetChildren()) do
if frame:IsA("Frame") then
frame:Destroy()
end
end
for i, connection in displayConnections do
connection:Disconnect()
end
table.clear(displayConnections)
if button.Name ~= "All" then
for _, object in pairs(game.ReplicatedStorage.ObjectFolder:GetChildren()) do
if object:GetAttribute("Type") == button.Name then
local uiButton = game.ReplicatedStorage.BuildingItem:Clone()
uiButton.Parent = player.PlayerGui.ScreenGui.Building.ScrollingFrame
uiButton.ItemName.Text = object.Name
uiButton.Cost.Text = "$"..tostring(object:GetAttribute("Price"))
uiButton.Name = object.Name
local camClone = object:Clone()
local camera = Instance.new("Camera")
camera.FieldOfView = 70
camera.Parent = uiButton.ViewportFrame
camClone.Parent = uiButton.ViewportFrame
uiButton.ViewportFrame.CurrentCamera = camera
local vpfModel = ViewportModel.new(uiButton.ViewportFrame, camera)
local cf, size = camClone:GetBoundingBox()
vpfModel:SetModel(camClone)
local theta = 0
local orientation = CFrame.new()
local distance = vpfModel:GetFitDistance(cf.Position)
table.insert(displayConnections, game:GetService("RunService").RenderStepped:Connect(function(dt)
theta = theta + math.rad(20 * dt)
orientation = CFrame.fromEulerAnglesYXZ(math.rad(-20), theta, 0)
camera.CFrame = CFrame.new(cf.Position) * orientation * CFrame.new(0, 0, distance)
end))
EnablePlacement()
end
end
else
for _, object in pairs(game.ReplicatedStorage.ObjectFolder:GetChildren()) do
local uiButton = game.ReplicatedStorage.BuildingItem:Clone()
uiButton.Parent = player.PlayerGui.ScreenGui.Building.ScrollingFrame
uiButton.ItemName.Text = object.Name
uiButton.Cost.Text = "$"..tostring(object:GetAttribute("Price"))
uiButton.Name = object.Name
local camClone = object:Clone()
local camera = Instance.new("Camera")
camera.FieldOfView = 70
camera.Parent = uiButton.ViewportFrame
camClone.Parent = uiButton.ViewportFrame
uiButton.ViewportFrame.CurrentCamera = camera
local vpfModel = ViewportModel.new(uiButton.ViewportFrame, camera)
local cf, size = camClone:GetBoundingBox()
vpfModel:SetModel(camClone)
local theta = 0
local orientation = CFrame.new()
local distance = vpfModel:GetFitDistance(cf.Position)
table.insert(displayConnections, game:GetService("RunService").RenderStepped:Connect(function(dt)
theta = theta + math.rad(20 * dt)
orientation = CFrame.fromEulerAnglesYXZ(math.rad(-20), theta, 0)
camera.CFrame = CFrame.new(cf.Position) * orientation * CFrame.new(0, 0, distance)
end))
EnablePlacement()
end
end
end)
end
end
-- Delete on MouseButton1Up
local selected
local confirmationConnections = {}
mouse.Button1Up:Connect(function()
if player.PlayerGui.ScreenGui.Building.Visible and mouse.Target:FindFirstAncestor("Structures"):FindFirstAncestor(player.Name) and not selected then
client.OpenUI(player.PlayerGui.ScreenGui.DeleteConfirmation)
selected = mouse.Target.Parent
game.SoundService.OpenUI:Play()
for i, connection in confirmationConnections do
connection:Disconnect()
end
table.clear(confirmationConnections)
table.insert(confirmationConnections, player.PlayerGui.ScreenGui.DeleteConfirmation.Yes.MouseButton1Click:Connect(function()
client.OpenUI(player.PlayerGui.ScreenGui.DeleteConfirmation)
selected:Destroy()
game.SoundService.CancelPlacement:Play()
selected = nil
end))
table.insert(confirmationConnections, player.PlayerGui.ScreenGui.DeleteConfirmation.No.MouseButton1Click:Connect(function()
client.OpenUI(player.PlayerGui.ScreenGui.DeleteConfirmation)
selected = nil
end))
end
end)
player.PlayerGui.ScreenGui.MainButtons.BuildButton.Button.MouseButton1Click:Connect(function()
if player.PlayerGui.ScreenGui.Building.Visible then
DisableStructures()
else
DisplayStructures()
end
end)
Example of a memory leak:
button1.MouseButton1Down:Connect(function()
button2.MouseButton1Down:Connect(function()
end)
button3.MouseButton1Down:Connect(function()
end)
end)
Every time you click button1, it creates new events to button2 and button3, none of which are disconnected upon clicking again, which causes a memory leak.