So I have finished making a block placement system but now I ran into a problem, the problem is that it is very laggy looping through the BlocksFolder everytime. So I want to rewrite it so it just snaps into a grid instead of getting the closest part and setting the position there.
Any help please.
local function findClosestPart()
local currentPart = nil
local currentClosestDir = nil
local currentClosestMag = nil
local mouseRay = currentCamera:ScreenPointToRay(mouse.X, mouse.Y)
for i,v in ipairs(BlocksFolder:GetDescendants()) do
if v:IsA("BasePart") then
local mouse3DPos = mouseRay:ClosestPoint(v.Position)
local magnitude = (v.Position - mouse3DPos).Magnitude
if not currentClosestMag or magnitude < currentClosestMag then
currentClosestMag = magnitude
currentPart = v
end
end
end
if currentPart and currentClosestMag <= closestPartMaxDistance then
local surfaceOffset = Vector3.new(3, 3, 3) -- Offset to determine surface positions
local surfaceIDs = {
Left = currentPart.Position - Vector3.new(surfaceOffset.X, 0, 0),
Right = currentPart.Position + Vector3.new(surfaceOffset.X, 0, 0),
Front = currentPart.Position - Vector3.new(0, 0, surfaceOffset.Z),
Back = currentPart.Position + Vector3.new(0, 0, surfaceOffset.Z),
DiagonalFrontLeft = currentPart.Position + Vector3.new(-surfaceOffset.X, 0, surfaceOffset.Z),
DiagonalFrontRight = currentPart.Position + Vector3.new(surfaceOffset.X, 0, surfaceOffset.Z),
DiagonalBackLeft = currentPart.Position + Vector3.new(-surfaceOffset.X, 0, -surfaceOffset.Z),
DiagonalBackRight = currentPart.Position + Vector3.new(surfaceOffset.X, 0, -surfaceOffset.Z),
}
if mouse.Target == nil then
local closestMag = nil
local rayDir = mouseRay.Direction
local rayOrigin = mouseRay.Origin
for surfaceId, pos in pairs(surfaceIDs) do
local dir = (pos - rayOrigin).Unit
local magnitude = (rayDir - dir).Magnitude
if not closestMag or magnitude < closestMag then
closestMag = magnitude
currentClosestDir = surfaceId
end
end
else
local mouse3DPos = mouseRay:ClosestPoint(currentPart.Position)
local closestMag = nil
for surfaceId, pos in pairs(surfaceIDs) do
local magnitude = (mouse3DPos - pos).Magnitude
if not closestMag or magnitude < closestMag then
closestMag = magnitude
currentClosestDir = surfaceId
end
end
end
if currentClosestDir then
return currentPart, currentClosestDir
end
end
end
local function display()
local mouseTarget = mouse.TargetSurface
local HumanoidRootPart = character:FindFirstChild("HumanoidRootPart") or character.PrimaryPart
if HumanoidRootPart then
if mouse.Target then
if (mouse.Target.Position - HumanoidRootPart.Position).Magnitude <= maxPlaceBlockRange then
blockPrediction = false
displayBlock.CFrame = CFrame.new(mouse.Target.Position)
local newPlacementCFrame = nil
if mouseTarget == Enum.NormalId.Top then
newPlacementCFrame = CFrame.new(mouse.Target.Position + Vector3.new(0, 3, 0))
elseif mouseTarget == Enum.NormalId.Bottom then
newPlacementCFrame = CFrame.new(mouse.Target.Position - Vector3.new(0, 3, 0))
elseif mouseTarget == Enum.NormalId.Left then
newPlacementCFrame = CFrame.new(mouse.Target.Position - Vector3.new(3, 0, 0))
elseif mouseTarget == Enum.NormalId.Right then
newPlacementCFrame = CFrame.new(mouse.Target.Position + Vector3.new(3, 0, 0))
elseif mouseTarget == Enum.NormalId.Front then
newPlacementCFrame = CFrame.new(mouse.Target.Position - Vector3.new(0, 0, 3))
elseif mouseTarget == Enum.NormalId.Back then
newPlacementCFrame = CFrame.new(mouse.Target.Position + Vector3.new(0, 0, 3))
end
placementCFrame = newPlacementCFrame
else
local closestPart, direction = findClosestPart()
local offsetVector = Vector3.new()
blockPrediction = true
currentClosestPart = closestPart
if closestPart and direction then
if tostring(direction) == "Left" then
offsetVector = Vector3.new(-3, 0, 0)
elseif tostring(direction) == "Right" then
offsetVector = Vector3.new(3, 0, 0)
elseif tostring(direction) == "Front" then
offsetVector = Vector3.new(0, 0, -3)
elseif tostring(direction) == "Back" then
offsetVector = Vector3.new(0, 0, 3)
elseif tostring(direction) == "DiagonalFrontLeft" then
offsetVector = Vector3.new(-3, 0, 3)
elseif tostring(direction) == "DiagonalFrontRight" then
offsetVector = Vector3.new(3, 0, 3)
elseif tostring(direction) == "DiagonalBackLeft" then
offsetVector = Vector3.new(-3, 0, -3)
elseif tostring(direction) == "DiagonalBackRight" then
offsetVector = Vector3.new(3, 0, -3)
end
local targetPos = closestPart.Position + offsetVector
displayBlock.CFrame = CFrame.new(targetPos)
placementCFrame = displayBlock.CFrame
closestPart = nil
direction = nil
end
end
else
local closestPart, direction = findClosestPart()
local offsetVector = Vector3.new()
blockPrediction = true
currentClosestPart = closestPart
if closestPart and direction then
if tostring(direction) == "Left" then
offsetVector = Vector3.new(-3, 0, 0)
elseif tostring(direction) == "Right" then
offsetVector = Vector3.new(3, 0, 0)
elseif tostring(direction) == "Front" then
offsetVector = Vector3.new(0, 0, -3)
elseif tostring(direction) == "Back" then
offsetVector = Vector3.new(0, 0, 3)
elseif tostring(direction) == "DiagonalFrontLeft" then
offsetVector = Vector3.new(-3, 0, 3)
elseif tostring(direction) == "DiagonalFrontRight" then
offsetVector = Vector3.new(3, 0, 3)
elseif tostring(direction) == "DiagonalBackLeft" then
offsetVector = Vector3.new(-3, 0, -3)
elseif tostring(direction) == "DiagonalBackRight" then
offsetVector = Vector3.new(3, 0, -3)
end
local targetPos = closestPart.Position + offsetVector
displayBlock.CFrame = CFrame.new(targetPos)
placementCFrame = displayBlock.CFrame
closestPart = nil
direction = nil
end
end
end
end