Can someone help me with this?
The block is not perfectly aligned to the grid. When I place a block on top of another block, it works fine but not with slabs.
But when I try placing a block on the side of another block, the preview starts flickering (it keeps switching very fast between being slightly in front of the target block and being inside it).
It only happens when placing blocks on the sides of other blocks, not on top or bottom.
Does anyone know how to fix it?
Honestly, my script looks pretty messy:
local GridSize = 4
local gridOffsets = {
[1] = {
Offset = 0.5,
},
[2] = {
Offset = 0.5,
},
[4] = {
Offset = 0.5,
},
}
local function getBlockPosition(vector3, blockSize, oX, oY, oZ)
local half = blockSize/2
return Vector3.new(
math.floor((vector3.X + half.X) / blockSize.X) * blockSize.X + oX,
math.floor((vector3.Y + half.Y) / blockSize.Y) * blockSize.Y + oY,
math.floor((vector3.Z + half.Z) / blockSize.Z) * blockSize.Z + oZ
)
end
local castParams = RaycastParams.new()
castParams.FilterType = Enum.RaycastFilterType.Exclude
castParams.FilterDescendantsInstances = {Player.Character}
local ovParams = OverlapParams.new()
ovParams.FilterType = Enum.RaycastFilterType.Exclude
ovParams.FilterDescendantsInstances = {self.PreviewModel, Player.Character}
RunService:BindToRenderStep("Preview", Enum.RenderPriority.Camera.Value, function()
if BuildingController.CurrentSelected == self then
local mouseLocation = UserInputService:GetMouseLocation()
local unityRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local cast = workspace:Raycast(unityRay.Origin, unityRay.Direction * 1000, castParams)
if cast then
local Size = self.PrimaryPart.Size
local sizeX = Size.X
local sizeY = Size.Y
local sizeZ = Size.Z
local surfaceX = math.round(cast.Normal.X)
local surfaceY = math.round(cast.Normal.Y)
local surfaceZ = math.round(cast.Normal.Z)
local targetSize = cast.Instance.Size
local scale = gridOffsets[GridSize].Scale and gridOffsets[GridSize].Scale*2 or 2
if surfaceX == 1 then
offsetX = sizeX/2 - scale
elseif surfaceX == -1 then
offsetX = -sizeX/2 + scale
end
if surfaceY == 1 then
offsetY = sizeY/2
elseif surfaceY == -1 then
offsetY = -sizeY/2
end
if surfaceZ == 1 then
offsetZ = sizeZ - scale
elseif surfaceZ == -1 then
offsetZ = -sizeZ/2 + scale
end
local overlapBool = false
local pos = getBlockPosition(cast.Position, Size, offsetX, offsetY, offsetZ)
self.LastValidCFrame = self.LastValidCFrame or self.PrimaryPart.CFrame
local targetCF = CFrame.new(pos) * CFrame.Angles(math.rad(self.y_Angle), math.rad(self.x_Angle), 0)
local ovParams = OverlapParams.new()
ovParams.FilterType = Enum.RaycastFilterType.Exclude
ovParams.FilterDescendantsInstances = { self.PreviewModel, Player.Character }
local hitbox = self.PreviewModel:FindFirstChild("Hitbox")
local prevHitboxCF = hitbox.CFrame
local prevPrimaryCF = self.PrimaryPart.CFrame
hitbox.CFrame = targetCF
local overlappingParts = workspace:GetPartsInPart(hitbox, ovParams)
if #overlappingParts > 0 then
local lastPos = self.LastValidCFrame.Position
local currentPos = targetCF.Position
local direction = Vector3.new(0, currentPos.Y - lastPos.Y, 0)
local step = 0.1
local safePos = lastPos
for i = 1, 30 do
local testPos = safePos + direction.Unit * step
hitbox.CFrame = CFrame.new(testPos)
local parts = workspace:GetPartsInPart(hitbox, ovParams)
if #parts > 0 then break end
safePos = testPos
end
local finalCF = CFrame.new(safePos) * CFrame.Angles(math.rad(self.y_Angle), math.rad(self.x_Angle), 0)
self.PrimaryPart.Parent:SetPrimaryPartCFrame(finalCF)
hitbox.CFrame = finalCF
self.LastValidCFrame = finalCF
else
self.PrimaryPart.Parent:SetPrimaryPartCFrame(targetCF)
self.LastValidCFrame = targetCF
end
end
end
end)