This is a support category for asking questions about how to get something done on the Roblox websites or how to do something on Roblox applications such as Roblox Studio.
You can write your topic however you want, but you need to answer these questions:
What do you want to achieve? Keep it simple and clear!
A grid placement system
What is the issue? Include screenshots / videos if possible!
Weird block offset when placing a part to the side of another part
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
changing Y offset
After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!
here is the script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlaceRemote = ReplicatedStorage.Remotes.Place
local PartsFolder = ReplicatedStorage.Parts
local gridSize = 2
local function SnapToGrid(pos, hitPart, PartClone)
return Vector3.new(
math.floor(pos.X / gridSize + 0.5) * gridSize,
hitPart.Position.Y + (PartClone.Size.Y / 2) + (hitPart.Size.Y / 2),
math.floor(pos.Z / gridSize + 0.5) * gridSize
)
end
PlaceRemote.OnServerEvent:Connect(function(player, partName, hitPos, normal, hitPart)
local part = PartsFolder:FindFirstChild(partName)
if not part or not hitPart then return end
local PartClone = part:Clone()
PartClone.Anchored = true
local offset = normal * (PartClone.Size.Y / 2)
local targetPos = hitPos + offset
local snappedPos = SnapToGrid(targetPos, hitPart, PartClone)
PartClone.Position = snappedPos
PartClone.Parent = workspace
end)
and here is the client script if needed:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlaceRemote = ReplicatedStorage.Remotes.Place
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
mouse.Button1Down:Connect(function()
if not player.Character then return end
local unitRay = mouse.UnitRay
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {player.Character}
local raycastResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, raycastParams)
if raycastResult then
local hit = raycastResult.Instance
local pos = raycastResult.Position
local normal = raycastResult.Normal
PlaceRemote:FireServer("BasicBrick", pos, normal, hit)
end
end)
In case that doesn’t work or you run into other issues, here’s mine:
local UserInputService = game:GetService("UserInputService")
local currentCamera = workspace.CurrentCamera
local PART = script.Parent
local GRIDSIZE = 2
UserInputService.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean)
if gameProcessedEvent or input.UserInputType ~= Enum.UserInputType.MouseMovement then
return
end
local inputPos: Vector3 = input.Position
local ray = currentCamera:ScreenPointToRay(inputPos.X, inputPos.Y)
local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 50)
if not raycastResult or not raycastResult.Instance then
return
end
local hitPart = raycastResult.Instance
if not hitPart:IsA("BasePart") then
return
end
local hitPos = raycastResult.Position
local sizeOffset = PART.Size / 2 * raycastResult.Normal
PART.Position = Vector3.new(
math.round((hitPos.X + sizeOffset.X) / GRIDSIZE) * GRIDSIZE,
math.round((hitPos.Y + sizeOffset.Y) / GRIDSIZE) * GRIDSIZE,
math.round((hitPos.Z + sizeOffset.Z) / GRIDSIZE) * GRIDSIZE
)
end)
How would I make the grid relative to the surface? here is my current code:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlaceRemote = ReplicatedStorage.Remotes.Place
local PartsFolder = ReplicatedStorage.Parts
local GRIDSIZE = 2
PlaceRemote.OnServerEvent:Connect(function(player, partName, hitPos, normal, hitPart)
local part = PartsFolder:FindFirstChild(partName)
if not part or not hitPart then return end
local PartClone = part:Clone()
PartClone.Anchored = true
PartClone.Parent = workspace
local offset = normal * (PartClone.Size.Y / 2)
local targetPos = hitPos + offset
local sizeOffset = PartClone.Size / 2 * normal
PartClone.Position = Vector3.new(
math.round((hitPos.X + sizeOffset.X) / GRIDSIZE) * GRIDSIZE,
math.round((hitPos.Y + sizeOffset.Y) / GRIDSIZE) * GRIDSIZE,
math.round((hitPos.Z + sizeOffset.Z) / GRIDSIZE) * GRIDSIZE
)
end)
here it does not change at all depending on the surface