Offset part to not clip inside other parts

I’m trying to make a placement system and i’m setting the parts position to Mouse.Hit.Position, this however, this makes the part move inside the part i’m placing it on kind of like this:
image

This is of course because i’m setting the pos of the middle of the part to Mouse.Hit.Position, so i tried offsetting the pos by half of the parts size based on what side of the part i am placing it on, like this:

		local surface = mouse.TargetSurface
		local offset = Vector3.new(0,0,0)
		if surface == Enum.NormalId.Top then
			offset = Vector3.new(0,part.Size.Y/2,0)
		elseif surface == Enum.NormalId.Bottom then
			offset = Vector3.new(0,-part.Size.Y/2,0)
		elseif surface == Enum.NormalId.Back then
			offset = Vector3.new(0,0,part.Size.Z/2)
		elseif surface == Enum.NormalId.Front then
			offset = Vector3.new(0,0,-part.Size.Z/2)
		elseif surface == Enum.NormalId.Right then
			offset = Vector3.new(part.Size.X/2,0,0)
		elseif surface == Enum.NormalId.Left then
			offset = Vector3.new(-part.Size.X/2,0,0)	
		end
		ghost.Position = mouse.Hit.Position + offset

(ghost is the part i am placing)
This works fine normally, however, when i rotate the wall i’m placing it on, the Normal Id’s get “rotated” too because a parts face normal is relative to the part itself. How would i offset the position of “ghost” so it won’t clip inside any parts i try to place it on without rotating “ghost”.

image

(I’m also going to implement rotating the part and i’m guessing that would mess up a lot of stuff but i’ll either figure that out on my own or more likely ask smarter ppl about it in another post lol)

Thanks for reading!

I believe I’ve already answered this question here:

You do need to replace LookVector and the size used in the calculation.

Top: UpVector
Bottom: -UpVector

Right: RightVector
Left: -RightVector

Front: LookVector
Back: -LookVector

You already have the relevant sizes in your code.

1 Like

Thanks,

		local surface = mouse.TargetSurface
		local target = mouse.Target
		local vector = nil
		local scale = {nil,1}
		if surface == Enum.NormalId.Top then
			vector = target.CFrame.UpVector
			scale = {ghost.Size.Y, 1}
		elseif surface == Enum.NormalId.Bottom then
			vector = -target.CFrame.UpVector
			scale = {ghost.Size.Y, -1}
		elseif surface == Enum.NormalId.Front then
			vector = target.CFrame.LookVector
			scale = {ghost.Size.X, 1}
		elseif surface == Enum.NormalId.Back then
			vector = -target.CFrame.LookVector
			scale = {ghost.Size.X, -1}
		elseif surface == Enum.NormalId.Right then
			vector = target.CFrame.RightVector
			scale = {ghost.Size.Z, 1}
		elseif surface == Enum.NormalId.Left then
			vector = -target.CFrame.RightVector
			scale = {ghost.Size.Z, -1}
		end
		
		-- The LookVector is where the front of the part is *relative to the part itself*.
		-- The LookVector has a magnitude (a length) of 1.
		-- We add half of the size of Part1 and Part0 to get the distance the parts should be apart.
		-- Finally, we multiply the distance by the LookVector and add it to the CFrame.
		
		ghost.CFrame = (mouse.Hit + (vector * (scale[1] / 2 * scale[2]))) * CFrame.fromEulerAnglesXYZ(0, math.rad(90), 0

Now i have this, i don’t know if this is what you meant but this code now rotates the part towards the camera because i’m manipulating the mouse.Hit vector. What do i need to change about my code to make the part i’m placing have a constant rotation not based on the camera position.

Sorry for the late reply, but here is the approach I would use. This is the from the same post that @busterbob64 linked, but I posted my own reply. I’d say mine is much better because it accounts for different part shapes and allows for more dynamic orientation. I also made an entire video explaining everything.

1 Like

While that does account for different part shapes, it isn’t exactly worth doing.

In Roblox, there are cuboids, wedges, spheres and meshes.

For the first three, my method works well enough. If you’re using meshes or if you care about being accurate, you might as well use the surface normal and position you got from raycasting. My method and the raycasting method I detailed above are more efficient methods since they do not use repetitive geometric collision checking.

From the looks of it, it seems to only account for cuboids accurately. It seems pretty inaccurate for wedges and spheres, especially at large sized wedges. I think it’s worth the slightly more taxing method over the fairly inaccurate one.

1 Like

Even still:

Right, but you’d need to account for the shapes of BOTH parts, not just the one you’re hitting with the raycast- there can still easily be collisions through your method. All in all, I think the method of repetitively checking parts in parts is a much better solution than yours for consistency purposes and accuracy.

1 Like

No you don’t.

If we assume the mesh will always touch the bounding box at some point (which, by definition, it must) then we do not need to do any special tests. If it doesn’t, the user can rotate it. This might sound like a flaw, but in practice it is not. Building objects in games are often placed in a grid, so it would make sense that the objects themselves are designed to fit into the grid.

Even still, if you find this flaw to be unacceptable you can still get around it by just firing two raycasts. This iterative approach is not necessary when you already have the geometry of both parts.

Additionally, I believe you are understating the performance impact of your method. For repositioning every frame, like in this case, you’re doing hundreds of expensive checks every second. While this may still allow you to run at a smooth 60 frames per second, I would imagine it would still take up a significant portion of frame time.

Capiche?

In all honesty, I literally cannot comprehend what you are saying in your first paragraph. Like, at all. Could you rephrase that?

Even still, if you find this flaw to be unacceptable you can still get around it by just firing two raycasts. This iterative approach is not necessary when you already have the geometry of both parts.

You don’t have the geometry of the part. You only have the size, the position, and a raycast normal to one specific location of each part. Accuracy wise, this is not equivalent to having the geometry of the part. On top of this, now you have to worry about where the second raycast is positioned, which is wonky because not only positioning, but also the fact that you would have to child the part to the workspace to even use the raycast. Now this issue has become a matter of simplicity versus complexity considering all of these new cases you’re adding on the spot, and I still think my solution is much better.

Regarding performance, this is the reason I added the line defining magnitude. You can adjust this value accordingly to how you think you should balance accuracy and performance.

1 Like

If you draw the smallest box around an object, it is guaranteed to hit a point on the object.

It’s simply a cast from the previous raycast position and the surface normal.

You can create DataModels yourself…

What do you mean by accuracy wise?

The normal and position returned is good enough for most cases, including this one.

I can only think of one case where your method would work, which are concave shapes, but:

Additionally, you can still use the first method without the additional raycast and it would work well enough for most cases regardless.

However, the solutions I gave above have mostly perfect accuracy and performance, with only a few edge cases that some don’t handle well. These edge cases are easily mitigated through careful design of objects.

Your solution will never be perfectly accurate nor performant, but it handles all cases. There are some niche cases where your solution may be beneficial, but for most cases my solution will always be more accurate and performant—which is why I still believe my solution is better.