For the last while now, I have been working on a building system for my game. I used a tutorial to make the basis for it. As the blocks I am placing with are 4x4, I want to snap the placing position of the block to 4 studs. I have tried to do this but every time it has glitched strangely. The map you place on is randomly generated.
What is happening is that tiles that have been generated randomly disappear where my mouse cursor is.
How can I fix this?
Here is my generation code in a server script:
local partspawn = 1950
local partcount = math.round((partspawn / 10) * 12)
local mapgenerateplace = Vector3.new((partspawn / 2) - partspawn, 0, (partspawn / 2) - partspawn)
local wk,pl = game:GetService("Workspace"),game:GetService("Players")
function spawnmap()
local db = false
local folder = Instance.new("Folder")
folder.Name = "Map"
folder.Parent = wk
for i = 1,partcount,1 do
local newpart = Instance.new("Part",folder)
local height = math.round((math.random(10, 40) / 8)) * 8
local rad = math.round(math.random(1, 8))
if rad == 1 then
newpart.Color = Color3.fromRGB(100, 100, 106)
newpart.Material = Enum.Material.Slate
newpart.Name = "Stone"
newpart.Size = Vector3.new(40, height, 40)
else
newpart.Color = Color3.fromRGB(40, 127, math.round(math.random(70, 110)))
newpart.Material = Enum.Material.Grass
newpart.Name = "Grass"
newpart.Size = Vector3.new(40, height, 40)
end
newpart.Position,newpart.Anchored = Vector3.new(mapgenerateplace.X + math.round(math.random(1, partspawn) / 40) * 40, math.round(mapgenerateplace.Y), mapgenerateplace.Z + math.round(math.random(1, partspawn) / 40) * 40),true
if newpart then
local clone = game.ReplicatedStorage.MapObjects.Tree:Clone()
clone.Parent = workspace
if newpart.Touched then
if db == false then
local parts = newpart:GetTouchingParts()
for i, v in pairs(parts) do
if v.Position == newpart.Position then
newpart:Destroy()
clone:Destroy()
end
end
end
end
if math.random(0, 4) == 1 then
if clone:FindFirstChild("Trunk") then
clone.Trunk.Position = Vector3.new(newpart.Position.X, newpart.Position.Y + height / 2, newpart.Position.Z)
clone.Leaves.Position = Vector3.new(clone.Trunk.Position.X, clone.Trunk.Position.Y + 10.5, clone.Trunk.Position.Z)
else
clone:Destroy()
end
else
clone:Destroy()
end
end
end
db = false
end
spawnmap()
Here is my placement code in a local script:
local replicatedStorage = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")
local runService = game:GetService("RunService")
local placeStructure = replicatedStorage:WaitForChild("PlaceStructure")
local structureFrame = script.Parent.BuildFrame
local structures = replicatedStorage:WaitForChild("Structures")
local player = game.Players.LocalPlayer
local char = player.Character or player.Character:Wait()
local humanoidRootPart = char:WaitForChild("HumanoidRootPart")
local mouse = player:GetMouse()
local yBuildingOffset = 0
local maxPlacingDistance = 50
local rKeyIsPressed = false
local placingStructure = false
for _, structureButton in pairs(structureFrame:GetChildren()) do
if structureButton:IsA("TextButton") then
structureButton.MouseButton1Up:Connect(function()
structureFrame.Visible = false
structureFrame.Parent.Delete.Visible = false
script.Parent.Instructions1.Visible = true
script.Parent.Instructions2.Visible = true
local yOrientation = 0
local goodToPlace = false
local placedStructure
if placingStructure == false then
placingStructure = true
local clientStructure = structures:FindFirstChild(structureButton.Name):Clone()
clientStructure.BrickColor = BrickColor.new("Forest green")
clientStructure.Material = "Neon"
clientStructure.CanCollide = false
clientStructure.Parent = workspace
yBuildingOffset = clientStructure.Size.Y / 2
local startingCFrame = CFrame.new(0, 0, 0)
clientStructure.CFrame = humanoidRootPart.CFrame:ToWorldSpace(startingCFrame)
runService.RenderStepped:Connect(function()
local mouseRay = mouse.UnitRay
local castRay = Ray.new(mouseRay.Origin, mouseRay.Direction * 1000)
local ignoreList = {clientStructure, char}
local hit, position = workspace:FindPartOnRayWithIgnoreList(castRay, ignoreList)
if hit and (not hit:IsA("Terrain") or not hit.Name:lower() == "terrain") and (humanoidRootPart.Position - clientStructure.Position).Magnitude < maxPlacingDistance then
goodToPlace = true
clientStructure.BrickColor = BrickColor.new("Forest green")
else
goodToPlace = false
clientStructure.BrickColor = BrickColor.new("Crimson")
end
local newAnglesCFrame = CFrame.Angles(0, math.rad(yOrientation), 0)
local newCFrame = CFrame.new(position.X, position.Y + yBuildingOffset, position.Z)
local cframeTable = table.pack(newCFrame:GetComponents())
--Set the Position
for i, v in pairs(cframeTable) do
--Edit:
cframeTable[i] = math.round(v / 4) * 4
end
local roundedCFrame = CFrame.new(table.unpack(cframeTable))
clientStructure.CFrame = roundedCFrame * newAnglesCFrame
--Positon Set
end)
UIS.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
rKeyIsPressed = true
local rotationSpeed = 5
while rKeyIsPressed do
wait()
if placingStructure == true then
yOrientation = yOrientation + math.deg(0.785398)
wait(0.25)
end
end
end
end)
UIS.InputEnded:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
rKeyIsPressed = false
end
end)
local inputConnection
inputConnection = UIS.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 and placingStructure == true then
if goodToPlace then
local structureCFrame = clientStructure.CFrame
placedStructure = placeStructure:InvokeServer(clientStructure.Name, structureCFrame)
if placedStructure then
placingStructure = false
clientStructure:Destroy()
structureFrame.Visible = true
script.Parent.Instructions1.Visible = false
script.Parent.Instructions2.Visible = false
inputConnection:Disconnect()
end
end
end
end)
UIS.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.X then
placingStructure = false
clientStructure:Destroy()
structureFrame.Visible = true
script.Parent.Instructions1.Visible = false
script.Parent.Instructions2.Visible = false
inputConnection:Disconnect()
end
end)
end
end)
end
end

3 comments
Do they reappear when your mouse cursor goes off of it?
Yes, this is confusing me a little as 3 tiles all around my mouse disappear at once.
If I just use math.round(v) it works perfectly but when I do math.round(v / 4) * 4 it stops working.