|If possible please write easy answers for me to understand when it comes to CFrame math! I'm still figuring out how it works. Thanks in advance.|
My goal here is to make a building system where I could snap objects to surfaces of other objects while still following a grid (like the Stamper Tool or something else similar.)
Currently I've only managed to make grid snapping (I deleted that part of the code.) Surface snap only works when I remove the grid snapping functionality and all the workarounds I could think of don't work correctly (or I'm probably just tired when I work with them).
What else can I do to make this happen?:
local PlayerCont = game:GetService("Players") local Mouse = PlayerCont.LocalPlayer:GetMouse() local PlacementCursor = Instance.new("Part", workspace) -- Since FilteringEnabled is true, we can -- make the player's cursor invisible to others. local SnapByStuds = 4 local States = { -- Non functional OFF = 0, BUILD = 1, EDIT = 2, COLOR = 3, WIRE = 4, CLIPBOARD = 5, REMOVE = 6 } local RotationStates -- does nothing for now -- Initialization PlacementCursor.Transparency = 0.8 -- 0.8 for now PlacementCursor.Anchored = true PlacementCursor.CanCollide = false PlacementCursor.CastShadow = false PlacementCursor.Size = Vector3.new(4, 4, 4) PlacementCursor.Material = "Neon" Mouse.TargetFilter = PlacementCursor local cmath = {} function cmath.even(x, returnNum, custCheck) local custN = custCheck or 1 if returnNum then return (x % custN) end return (x % custN) == 0 end function cmath.nearest(x, roundnum) local rounding = roundnum or 1 if typeof(x) == "Vector3" then local X, Y, Z = x.X, x.Y, x.Z local rX, rY, rZ = cmath.even(X, true, rounding) / rounding, cmath.even(Y, true, rounding) / rounding, cmath.even(Z, true, rounding) / rounding if rX > 0.5 then X = math.ceil(X / rounding) * rounding + (SnapByStuds/2) else X = math.floor(X / rounding) * rounding + (SnapByStuds/2) end if rY > 0.5 then Y = math.ceil(Y / rounding) * rounding + (SnapByStuds/2) else Y = math.floor(Y / rounding) * rounding + (SnapByStuds/2) end if rZ > 0.5 then Z = math.ceil(Z / rounding) * rounding + (SnapByStuds/2) else Z = math.floor(Z / rounding) * rounding + (SnapByStuds/2) end return Vector3.new(X, Y, Z) else -- numbers only not used for now end end -- =========================================================== -- =========================================================== ACTUAL FUNCTIONS -- =========================================================== function DisplayNewPosition() -- Something to improve on. local Normal = Vector3.FromNormalId(Mouse.TargetSurface) local Position = Mouse.Hit.p local CursorCFrame = Mouse.Hit local Anchor = Mouse.Target if CursorCFrame ~= nil and Anchor ~= nil then local ObjectHit = Anchor.CFrame -- Anchor to center of object + rotation local ObjectSpace = Anchor.CFrame:ToObjectSpace(CFrame.new(Position)) * CFrame.Angles(0, 0, 0) local ObjectRotation = Anchor.CFrame - Anchor.CFrame.Position local RotatedNormal = (ObjectRotation * Normal) * (PlacementCursor.Size / 2) --print(RotatedNormal * PlacementCursor.Size) local FinalFormulation = (ObjectHit * ObjectSpace) + RotatedNormal PlacementCursor.CFrame = FinalFormulation end end function RequestAddition() -- nothing yet end Mouse.Move:Connect(DisplayNewPosition)
Thanks (again) in advance!