I’ve been working on a building game, this game has a custom grid system I made. But I’ve come across an issue recently, where wedges have bugged placement.
Basically, what I mean by this, is that when the player rotates a wedge, it errors the building system. It causes objects to be placed in the wrong positions.
This is my code:
--// Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputs = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--// Variables
local Blocks = ReplicatedStorage:WaitForChild("Blocks")
local Events = ReplicatedStorage:WaitForChild("Events")
local WorldData = workspace:WaitForChild("WorldData")
local Player = Players.LocalPlayer
local Mouse = Player:GetMouse()
local PlayerUI = Player.PlayerGui:WaitForChild("PlayerUI")
local BlockProperties = PlayerUI:WaitForChild("BlockProperties")
local CurrentPlaceholder = nil
Player:SetAttribute("EditMode", "BUILD")
Player:SetAttribute("BlockShape", "Block")
Player:SetAttribute("BlockColor", BrickColor.White())
Player:SetAttribute("BlockMaterial", Enum.Material.Plastic)
BlockProperties.Visible = false
local ClickDelay = 0.05
local OnDelay = false
task.wait(1)
local function CreatePlaceholder()
if CurrentPlaceholder ~= nil then
CurrentPlaceholder:Destroy()
CurrentPlaceholder = nil
end
local Block = Blocks:FindFirstChild(Player:GetAttribute("BlockShape"))
if Block then
Block = Block:Clone()
Block.Transparency = 0.5
Block.CanCollide = false
Block.Parent = workspace
CurrentPlaceholder = Block
end
end
local function ReturnCalculated(Offset)
local Target = Mouse.Target
if Target then
local cf = CFrame.new(Target.Position + Offset)
local convertedCF = Target.CFrame:ToWorldSpace(cf)
--[[
local cf = CFrame.new(Target.Position + Offset)
local convertedCF = Target.CFrame:ToObjectSpace(cf)
]]
return convertedCF
end
end
local function CalculatePosition(targetSurface)
local GridStep = 3
if targetSurface == "Front" then
local convertedCF = ReturnCalculated(Vector3.new(0, 0, -GridStep))
return convertedCF
elseif targetSurface == "Back" then
local convertedCF = ReturnCalculated(Vector3.new(0, 0, GridStep))
return convertedCF
elseif targetSurface == "Left" then
local convertedCF = ReturnCalculated(Vector3.new(-GridStep, 0, 0))
return convertedCF
elseif targetSurface == "Right" then
local convertedCF = ReturnCalculated(Vector3.new(GridStep, 0, 0))
return convertedCF
elseif targetSurface == "Top" then
local convertedCF = ReturnCalculated(Vector3.new(0, GridStep, 0))
return convertedCF
elseif targetSurface == "Bottom" then
local convertedCF = ReturnCalculated(Vector3.new(0, -GridStep, 0))
return convertedCF
end
end
Mouse.Button1Down:Connect(function()
if WorldData.Permissions:FindFirstChild(Player.Name) then
if Mouse.Target ~= nil then
if OnDelay == false then
OnDelay = true
if Mouse.Target.Parent == workspace.Blocks then
script.Highlight.Adornee = nil
if Player:GetAttribute("EditMode") == "BUILD" then
local BlockData = {
name = CurrentPlaceholder.Name,
cframe = CurrentPlaceholder.CFrame,
color = Player:GetAttribute("BlockColor"),
material = Player:GetAttribute("BlockMaterial"),
}
script.Place:Play()
Events.BlockServer:FireServer("BUILD", BlockData)
elseif Player:GetAttribute("EditMode") == "DELETE" then
local BlockData = {
target = Mouse.Target,
}
Events.BlockServer:FireServer("DELETE", BlockData)
elseif Player:GetAttribute("EditMode") == "PAINT" then
local BlockData = {
target = Mouse.Target,
color = Player:GetAttribute("BlockColor"),
material = Player:GetAttribute("BlockMaterial"),
}
Events.BlockServer:FireServer("PAINT", BlockData)
end
end
task.wait(ClickDelay)
OnDelay = false
end
end
end
end)
UserInputs.InputBegan:Connect(function(input, gP)
if WorldData.Permissions:FindFirstChild(Player.Name) then
if WorldData.Permissions[Player.Name].Value < 3 then
if not gP then
if input.KeyCode == Enum.KeyCode.Q then
if Player:GetAttribute("EditMode") == "BUILD" then
Player:SetAttribute("EditMode", "PAINT")
elseif Player:GetAttribute("EditMode") == "PAINT" then
Player:SetAttribute("EditMode", "DELETE")
elseif Player:GetAttribute("EditMode") == "DELETE" then
Player:SetAttribute("EditMode", "VIEWER")
elseif Player:GetAttribute("EditMode") == "VIEWER" then
Player:SetAttribute("EditMode", "BUILD")
end
elseif input.KeyCode == Enum.KeyCode.R then
if CurrentPlaceholder then
CurrentPlaceholder.CFrame *= CFrame.Angles(0, math.rad(90), 0)
end
elseif input.KeyCode == Enum.KeyCode.T then
if CurrentPlaceholder then
CurrentPlaceholder.CFrame *= CFrame.Angles(0, 0, math.rad(90))
end
elseif input.KeyCode == Enum.KeyCode.LeftAlt then
if Mouse.Target ~= nil then
Player:SetAttribute("BlockColor", Mouse.Target.BrickColor)
Player:SetAttribute("BlockMaterial", Mouse.Target.Material)
end
end
end
end
end
end)
CreatePlaceholder()
Mouse.TargetFilter = CurrentPlaceholder
RunService.RenderStepped:Connect(function()
if WorldData.Permissions:FindFirstChild(Player.Name) then
if WorldData.Permissions[Player.Name].Value < 3 then
PlayerUI.Mode.Visible = true
Player:GetAttributeChangedSignal("BlockShape"):Connect(function()
CreatePlaceholder()
Mouse.TargetFilter = CurrentPlaceholder
end)
-- UI
local EditMode = Player:GetAttribute("EditMode")
PlayerUI.Mode.Text = EditMode .. " MODE"
BlockProperties.List.Color.Frame.BackgroundColor3 = Player:GetAttribute("BlockColor").Color
BlockProperties.List.Materials.Frame.ViewportFrame.Block.Material = Player:GetAttribute("BlockMaterial")
BlockProperties.List.Shape.Display.Text = Player:GetAttribute("BlockShape")
if Mouse.Target ~= nil then
if Mouse.Target:FindFirstChild("SIGN") then
PlayerUI.Sign.Text = Mouse.Target.SIGN.Value
PlayerUI.Sign.Visible = true
else
PlayerUI.Sign.Text = ""
PlayerUI.Sign.Visible = false
end
else
PlayerUI.Sign.Text = ""
PlayerUI.Sign.Visible = false
end
-- BUILD STUFF
CurrentPlaceholder.BrickColor = Player:GetAttribute("BlockColor")
CurrentPlaceholder.Material = Player:GetAttribute("BlockMaterial")
if EditMode == "BUILD" then
BlockProperties.Visible = true
script.Highlight.OutlineColor = Color3.fromRGB(0, 130, 255)
script.Highlight.Adornee = nil
CurrentPlaceholder.Transparency = 0.25
if Mouse.Target ~= nil then
if Mouse.Target.Parent == workspace.Blocks then
local posOffset = CalculatePosition(Mouse.TargetSurface.Name)
CurrentPlaceholder.CFrame = posOffset
end
else
CurrentPlaceholder.Position = Vector3.new(0, 0, 0)
CurrentPlaceholder.Transparency = 1
end
elseif EditMode == "DELETE" then
BlockProperties.Visible = false
script.Highlight.OutlineColor = Color3.fromRGB(255, 0, 0)
CurrentPlaceholder.Transparency = 1
if Mouse.Target ~= nil then
if Mouse.Target.Parent == workspace.Blocks then
script.Highlight.Adornee = Mouse.Target
else
script.Highlight.Adornee = nil
end
else
script.Highlight.Adornee = nil
end
elseif EditMode == "PAINT" then
BlockProperties.Visible = true
script.Highlight.OutlineColor = Color3.fromRGB(0, 200, 0)
CurrentPlaceholder.Transparency = 1
if Mouse.Target ~= nil then
if Mouse.Target.Parent == workspace.Blocks then
script.Highlight.Adornee = Mouse.Target
else
script.Highlight.Adornee = nil
end
else
script.Highlight.Adornee = nil
end
else
PlayerUI.Mode.Visible = false
BlockProperties.Visible = false
CurrentPlaceholder.Transparency = 1
script.Highlight.Adornee = nil
end
else
PlayerUI.Mode.Visible = false
BlockProperties.Visible = false
CurrentPlaceholder.Transparency = 1
script.Highlight.Adornee = nil
end
end
end)
The functions that calculate placeholder movement are ReturnCalculated and CalculatePosition.
If you are trying to help, please include code examples and/or explanations.
Edit: Incase you were wondering, I’ve tried to use :ToObjectSpace and :ToWorldSpace, but it just caused the placeholder to move by 2 block steps. And, the blocks are 3, 3, 3.