I’ve created a building system that places a 4x4x4 block on a 4x4 grid, while it works nicely, it doesn’t let me place blocks on certain sides of the blocks.
I’ve tried rewriting the script multiple times to see if I could get a different outcome but I keep getting the same outcome.
This is my main building script.
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BlockFolder = ServerStorage:WaitForChild("Blocks")
local BlockTemplate = BlockFolder:WaitForChild("Block")
local SoundFolder = ServerStorage:WaitForChild("Sounds")
local PlaceSound = SoundFolder:WaitForChild("Placed")
local GridSize = 4
local playerBlocks = {}
local function hasBuildTool(player)
local character = player.Character
if character then
local tool = character:FindFirstChild("Build")
return tool and tool:IsA("Tool")
end
return false
end
local function hasDestroyTool(player)
local character = player.Character
if character then
local tool = character:FindFirstChild("Delete")
return tool and tool:IsA("Tool")
end
return false
end
local function getGridPosition(position)
local x = math.floor(position.X / GridSize + 0.5) * GridSize
local y = math.floor(position.Y / GridSize + 0.5) * GridSize
local z = math.floor(position.Z / GridSize + 0.5) * GridSize
return Vector3.new(x, y, z)
end
local function placeBlock(player, mousePosition, selectedColor, selectedMaterial)
if not hasBuildTool(player) then return end
local color = selectedColor or Color3.new(1, 1, 1)
local material = selectedMaterial or "Plastic"
local gridPosition = getGridPosition(mousePosition)
local existingBlock = false
for _, block in pairs(Workspace:WaitForChild("Blocks"):GetChildren()) do
if (block.Position - gridPosition).magnitude < GridSize then
existingBlock = true
break
end
end
if existingBlock then
return
end
local newBlock = BlockTemplate:Clone()
newBlock.Position = gridPosition
newBlock.Parent = Workspace:WaitForChild("Blocks")
newBlock.Color = color
if Enum.Material[material] then
newBlock.Material = Enum.Material[material]
else
newBlock.Material = Enum.Material.Plastic
end
newBlock:SetAttribute("Creator", player.UserId)
if not playerBlocks[player] then
playerBlocks[player] = {}
end
table.insert(playerBlocks[player], newBlock)
local placeSound = PlaceSound:Clone()
placeSound.Parent = newBlock
placeSound:Play()
placeSound.Ended:Connect(function()
placeSound:Destroy()
end)
end
local function deleteBlock(player, mousePosition)
if not hasDestroyTool(player) then return end
local gridPosition = getGridPosition(mousePosition)
local ray = Ray.new(gridPosition + Vector3.new(0, 5, 0), Vector3.new(0, -10, 0))
local hitPart = Workspace:FindPartOnRay(ray, player.Character)
if hitPart and hitPart.Parent == Workspace:WaitForChild("Blocks") then
local creatorId = hitPart:GetAttribute("Creator")
if creatorId == player.UserId then
hitPart:Destroy()
end
end
end
Players.PlayerRemoving:Connect(function(player)
if playerBlocks[player] then
for _, block in pairs(playerBlocks[player]) do
block:Destroy()
end
playerBlocks[player] = nil
end
end)
game.ReplicatedStorage.Events.PlaceBlock.OnServerEvent:Connect(function(player, mousePosition, selectedColor, selectedMaterial)
placeBlock(player, mousePosition, selectedColor, selectedMaterial)
end)
game.ReplicatedStorage.Events.DeleteBlock.OnServerEvent:Connect(function(player, mousePosition)
deleteBlock(player, mousePosition)
end)
ReplicatedStorage.Events.SetColor.OnServerEvent:Connect(function(player, newColor)
local selectedColor = player:FindFirstChild("SelectedColor")
if selectedColor then
selectedColor.Value = newColor
end
end)
ReplicatedStorage.Events.SetMaterial.OnServerEvent:Connect(function(player, newMaterial)
local selectedMaterial = player:FindFirstChild("SelectedMaterial")
if selectedMaterial then
selectedMaterial.Value = newMaterial
end
end)
Please let me know what I should change, I’ve been struggling at this and block placement has not been my number one thing.