I want players to be able to place blocks when they click, kind of like in minecraft. However, I can’t figure out how to detect what face of a part a player clicks on without using something like surface guis or multiple parts.
I’ve thought about comparing the position a player clicks on to the position of the block they clicked but I can’t figure out how that would work with blocks that are other shapes than cubes.
If index is a number, returns all arguments after argument number index . Otherwise, index must be the string "#" , and select returns the total number of extra arguments it received.
If you want to be able to place blocks on the side you click, then you can use raycasting and use the normal after clicking the mouse button. The normal is a vector that is perpendicular to a surface
local Mouse = Player:GetMouse()
local Camera = workspace.CurrentCamera
local ray = Camera:ViewportToRay(Mouse.X, Mouse.Y, 1)
-- this is where you customise your raycast params to your liking
local params = RaycastParams.new()
local result = workspace:Raycast(ray.Origin, ray.Direction * 300, params)
if result then
local part = result.Instance
local block = -- the block you want to position
-- "block_pos" is the position where you want the block to be placed after clicking
local block_pos = part.Position + result.Normal * ((part.Size + block.Size) * 0.5)
end
But more generally, if you do want the side the player clicks on, then you can use the dot product to compare each and every directional vector of the part touched with the surface normal, since if the raycast hits a face, the normal of the raycast and the normal of that face will be in the same direction. We use the Right/Up/Look vectors because they are vectors perpendicular to the surfaces of the parts, hence why we used them as normals:
local CF = part.CFrame
local normals = {
Left = -CF.RightVector;
Right = CF.RightVector;
Bottom = -CF.UpVector;
Top = CF.UpVector;
Back = -CF.LookVector;
Front = CF.LookVector;
}
for face, surface_normal in pairs(normals) do
if surface_normal:Dot(result.Normal) >= 0.999 then
print("The " .. dir .. " face was hit")
break
end
end