sorry I’m here so late hopefully you’ll see this the problem is with the Raycast the ray cast position is directly on the surface of the part and since the raycast position is so close theres two options the grid function either makes it inside the block or outside the block so sadly you cant just use a simple grid system so you have to find the position of the block outside the block or grid you want to put it on so first we have to find the distance between the ray instance position and the ray position if we just get the position one will always stay the same and one could a position could be very high on the x y or z when we do need that
local x, y, z = CFrame.new(ray.Position - ray.Instance.Position):GetComponents()
Then we get the absolute value of all the vectors of all of them because we need to find the highest value to know which axis to put the block on then we get the actual value of the vectors to position later we also put it until tables to find the values easier without making the code look too messy
local xabs = math.abs(x)
local yabs = math.abs(y)
local zabs = math.abs(z)
local tableofvectors = {x,y,z}
local tableofabsvectors = {xabs,yabs,zabs}
then we get the highest value of the absolute vectors to know the axis that will be changed by unpacking the table of absolute vectors
local max = math.max(table.unpack(tableofabsvectors))
After we make a variable which i call finder to find the axis we need using the value of max
just to make it clear we are NOT FINDING THE VALUE we are finding the index because the xyz is in order so now we know the axis
local finder = table.find(tableofabsvectors,max)
Then we go over and make another table then using the index we found using the finder we find the axis and the value we need then using the finder we make a new vector finding the index for a value in the table of tableofvectors then multiplying it by a value that fits your blocks my blocks are 3x3x3 and i put 2 as my value
local Ltable = {[1] = 0,[2] = 0,[3] = 0}
Ltable[finder] = tableofvectors[finder] * 2
Lasty we use to world space to set a new origin for our blocks so our blocks arent positioned near the position 0,0,0 in workspace using the Ltable then we return the cframe we get
local cframe ray.Instance.CFrame:ToWorldSpace(CFrame.new(Vector3.new(Ltable[1],Ltable[2],Ltable[3])))
return cframe
This is how you call this function and use it
local newsnap = Snap(ray)
part.CFrame = newsnap
This is the whole function
local function Snap(ray)
--get the distance of the ray and the instance
local x, y, z = CFrame.new(ray.Position - ray.Instance.Position):GetComponents()
-- get the aboluste values for later
local xabs = math.abs(x)
local yabs = math.abs(y)
local zabs = math.abs(z)
--Make tables to keep coode clean
local tableofvectors = {x,y,z}
local tableofabsvectors = {xabs,yabs,zabs}
--get the highest number out of the the three absoulte values of the vectors to get the axis
local max = math.max(table.unpack(tableofabsvectors))
-- print(max)
--NOT getting the value but getting the index so later we can use that index to find the actual values so its not just one sided
local finder = table.find(tableofabsvectors,max)
--print(finder)
--local vtable = {[1] = ray.Instance.Position.X,[2] = ray.Instance.Position.Y,[3] = ray.Instance.Position.Z}
--vtable[finder] = tableofvectors[finder]
--we make a table to plug into the vector3
local Ltable = {[1] = 0,[2] = 0,[3] = 0}
--we change the table because we dont know the actual value of the finder so we couldent change it before
Ltable[finder] = tableofvectors[finder] * 2
-- print(tableofvectors)
--We make the orgin or you could say the 0,0,0 point in workspace the ray instance position (is not global and does not change anything it just gives a cframe)
--if we did not change the orgin it would appear close the the spawnlocation in the workspace (the spawnlocation is close to the 0,0,0 point in workspace)
local cframe = ray.Instance.CFrame:ToWorldSpace(CFrame.new(Vector3.new(Ltable[1],Ltable[2],Ltable[3])))
return cframe
--return {PosX,PosY,PosZ}
end