Rotating block on grid building system breaks stuff

So im trying to make a basic game where you can build freely, but when you rotate a block, the placement calculation code breaks entirely. Please help. urgently as possible.


(The error occured when i made the next cube, and rotated it 90 degrees to the left, this breaks for all directions too. it’s odd.)
Heres a recording, the blocks are 3 by 3 on studs. When i rotate it any direction. it messes up , and the block clips into itself, how do i fix this?

Code:

local Mouse = game.Players.LocalPlayer:GetMouse() local CF local Orientation = script:FindFirstChildOfClass("Vector3Value") local Position local PreviewCF = CFrame.new() local Limit = 25 local part local X local Y local Z local cooldown = false local TS = game:GetService("TweenService") local SurfaceVectors = {	Top = Vector3.new(0, 1, 0),	Bottom = Vector3.new(0, -1, 0),	Left = Vector3.new(-1, 0, 0),	Right = Vector3.new(1, 0, 0),	Front = Vector3.new(0, 0, -1),	Back = Vector3.new(0, 0, 1), } local GridSize = 3 local UIS = game:GetService("UserInputService") UIS.InputBegan:Connect(function(input,gp)	if gp then return end	if input.KeyCode == Enum.KeyCode.R then	if Orientation.Value.Y == 360 then	Orientation.Value = Orientation.Value + Vector3.new(0,-270,0)	else	Orientation.Value = Orientation.Value + Vector3.new(0,90,0)	end	end end) UIS.InputBegan:Connect(function(input,gp)	if gp then return end	if input.KeyCode == Enum.KeyCode.Y then	if Orientation.Value.Z == -360 then	Orientation.Value = Orientation.Value + Vector3.new(0,0,270)	else	Orientation.Value = Orientation.Value + Vector3.new(0,0, -90)	end	end end) UIS.InputBegan:Connect(function(input,gp)	if gp then return end	if input.KeyCode == Enum.KeyCode.T then	if Orientation.Value.X == 360 then	Orientation.Value = Orientation.Value + Vector3.new(-270,0,0)	else	Orientation.Value = Orientation.Value + Vector3.new(90,0,0)	end	end end) script.Parent.Activated:Connect(function()	if cooldown == false then	cooldown = true	local distance = (Mouse.Hit.p - script.Parent.Parent.HumanoidRootPart.Position).Magnitude	if distance < Limit then	local Normal = Mouse.TargetSurface	local hitblock = Mouse.Target	script.Parent.place:FireServer(PreviewCF)	end	wait(.05)	cooldown = false	end end) game:GetService("RunService").RenderStepped:Connect(function()	local surface = Mouse.TargetSurface.Name	local surfaceVector = SurfaceVectors[surface]	local adjustedX = Mouse.Hit.Position.X + surfaceVector.X	local adjustedY = Mouse.Hit.Position.Y + surfaceVector.Y	local adjustedZ = Mouse.Hit.Position.Z + surfaceVector.Z	print(surface)	local xPos = math.round(adjustedX / GridSize) * GridSize	local yPos = math.round(adjustedY/ GridSize) * GridSize	local zPos = math.round(adjustedZ / GridSize) * GridSize	PreviewCF = CFrame.new(Vector3.new(xPos,yPos,zPos))*CFrame.fromEulerAnglesXYZ(math.rad(Orientation.Value.X),math.rad(Orientation.Value.Y),math.rad(Orientation.Value.Z)) end) script.Parent.Equipped:Connect(function()	part = game.ReplicatedStorage.Block:Clone()	part.Transparency = .5	part.CanCollide = false	part.Parent = game.Workspace.Camera	Mouse.TargetFilter = part	while wait() do	if part ~= nil then	part.BillboardGui.TextLabel.Text = "("..tostring(Orientation.Value)..")"	TS:Create(part,TweenInfo.new(0.05,Enum.EasingStyle.Linear),{CFrame = PreviewCF}):Play()	end	end end) script.Parent.Unequipped:Connect(function()	part:Destroy() end) 

orientation’s a part of cframe you might have a race condition where when you press the rotate button it draws from the old position instead

2 Likes

could you elaborate? i dont quite understand

when you press the button to rotate the block it pulls from the old position instead of the new one

wait nevermind print out xpos ypos and zpos each time it might just change the cframe slightly enough that math.round returns a smaller value than before

1 Like


Figured this might be the problem… the surface face system doesnt work right,

local SurfaceVectors = {	Top = Vector3.new(0, 1, 0),	Bottom = Vector3.new(0, -1, 0),	Left = Vector3.new(-1, 0, 0),	Right = Vector3.new(1, 0, 0),	Front = Vector3.new(0, 0, -1),	Back = Vector3.new(0, 0, 1), } game:GetService("RunService").RenderStepped:Connect(function()	local surface = Mouse.TargetSurface.Name	local surfaceVector = SurfaceVectors[surface]	local adjustedX = Mouse.Hit.Position.X + surfaceVector.X	local adjustedY = Mouse.Hit.Position.Y + surfaceVector.Y	local adjustedZ = Mouse.Hit.Position.Z + surfaceVector.Z	print(surface)	local xPos = math.round(adjustedX / GridSize) * GridSize	local yPos = math.round(adjustedY/ GridSize) * GridSize	local zPos = math.round(adjustedZ / GridSize) * GridSize	PreviewCF = CFrame.new(Vector3.new(xPos,yPos,zPos))*CFrame.fromEulerAnglesXYZ(math.rad(Orientation.Value.X),math.rad(Orientation.Value.Y),math.rad(Orientation.Value.Z)) end) 

IF there was a way to make work on all directions ,thatd be nice, acause it only works on one axis currently

you’ll have to convert the position to object space then convert it back into world space

1 Like

how do i do so, i remember messing with object space and world space and i got very frustrated

originCFrame:ToWorldSpace(originCFrame:ToObjectSpace(originCFrame) + Offset); 

something like this I’m really tired right now but essentially you add the offset to the originCF’s object space then convert it back to world space using origin CFrame, if you just add it to the world space it won’t work when rotated because it doesn’t face the same way

1 Like

im still so confused sorry, just write the code or something

local m_hit_x = Mouse.Hit.Position.X; local m_hit_y = Mouse.Hit.Position.Y; local m_hit_z = Mouse.Hit.Position.Z; local cf_position = CFrame.new(Vector3.new(m_hit_X,m_hit_Y,m_hit_Z)); local cf_to_object_space = cf_position:ToObjectSpace(cf_position) + surfaceVector; local offset = cf_position:ToWorldSpace(cf_to_object_space); --// change xPos, yPos, zPos to use offset.X, offset.Y, offhit.Z PreviewCF = CFrame.new(Vector3.new(xPos,yPos,zPos))*CFrame.fromEulerAnglesXYZ(math.rad(Orientation.Value.X),math.rad(Orientation.Value.Y),math.rad(Orientation.Value.Z)) 
1 Like


Tried putting that in, unfortunately didnt work, any possible code fixes? sorry for the late respond time, I was out sick.

P.S thank you for helping me

local surface = Mouse.TargetSurface.Name	local surfaceVector = SurfaceVectors[surface]	local m_hit_x = Mouse.Hit.Position.X;	local m_hit_y = Mouse.Hit.Position.Y;	local m_hit_z = Mouse.Hit.Position.Z;	local adjustedZ = Mouse.Hit.Position.Z + surfaceVector.Z	local cf_position = CFrame.new(Vector3.new(m_hit_x,m_hit_y,m_hit_z));	local cf_to_object_space = cf_position:ToObjectSpace(cf_position + surfaceVector);	local offset = cf_position:ToWorldSpace(cf_to_object_space);	local xPos = math.round(offset.X / GridSize) * GridSize	local yPos = math.round(offset.Y / GridSize) * GridSize	local zPos = math.round(offset.Z / GridSize) * GridSize	--// change xPos, yPos, zPos to use offset.X, offset.Y, offhit.Z	PreviewCF = CFrame.new(Vector3.new(xPos,yPos,zPos))*CFrame.fromEulerAnglesXYZ(math.rad(Orientation.Value.X),math.rad(Orientation.Value.Y),math.rad(Orientation.Value.Z)) 

The issue is likely due to how you’re using Mouse.TargetSurface.Name. When a block is rotated, the surface on its (side) is no longer the one which would be there if it was not rotated. This makes your surfaceVector wrong and thus your block is offseted incorrectly. You should instead try finding the unrotated surface name of the block (as in, what surface you would have hit if the target was not rotated).

any idea on how i would rotate the vector, accordingly to the blocks orientation?

Not really

You could just simulate it ig

like you see theres 3 rotations on X and 2 on Y, for the ones on X you change the value of (surface1) to that of (surface2) and (surface2) to (surface3) and so on for 3 times, and then the one for Y, in which you might instead be doing it for like (surface1) to (surface5) because rotating on Y axis would have different surfaces that are considered “next to” (surface1) than on the X axis.