Block Placement System Help (Positioning the blocks relative to other parts?)

I’m trying to make a placement system for my game. I’m sure by now all of you know how terrible I am with CFrame and math so sorry if this is kind of a silly question. I know of the tricks used by some people to make a grid placement system, but I’m wondering how I could make a system where the part is always bouncing off the other parts perfectly?

I know that’s probably a poor way to word it, but basically, with my current system, when the player moves the part, it goes inside other parts:

PlayAb
(The transparent brown part is the one I’m moving)

Ideally, it would somehow move so that it’s not going through anything else:


(Instead of going through the wall, the part is now touching the side of it.)
PlayAb
(Another point of view just to help. See how it’s now “bouncing” off the wall and not into it?)

I am currently just moving it to the mouse’s position with SetPrimaryPartCFrame() (It’s actually a model shhh don’t tell anybody):

mouse.Move:connect(function()
  if item then
	item:SetPrimaryPartCFrame(CFrame.new(mouse.Hit.p))
  end
end)

I did some really basic stuff but that only worked on one axis. I’m really lost here and help would be appreciated.

5 Likes

So, what you’ll need to do is find the surface normal (the direction that the surface is facing). Then…

local endPos = mousePos + (normal * halfDragObjectSize)
5 Likes

Thanks! How should I go about figuring out the surface normal though? Also, is it for the part I’m moving or the part I’m touching?

Looking at the mouse API now. It seems that the mouse unfortunately does not return the normal of the surface that it hit. It does give you the face as an enum, like Front, Back, Left… ect. We can make a dictionary for these and map them to normal’s as vector3’s, but this will be a problem if you are also using wedgeparts or meshparts. You would need a more robust system in that case.

If you would like to make a more robust system, you are going to want to use raycasting instead of mouse.Hit, since that will return the actual hit surface normal.

3 Likes

So if I do raycasting, I would then use that formula you wrote? Also, where would I cast the ray from? Like from the camera position or something to where the mouse hit is or?

Sorry if this is silly.

1 Like
local MAX_PLACEMENT_DISTANCE = 200

local ignoreList = {}
-- The mouse ray is only one stud long so we need to make a new ray that is longer.
local mouseRay = mouse.UnitRay
local newRay = Ray.new(mouseRay.Origin, mouseRay.Unit*MAX_PLACEMENT_DISTANCE)
local target, pos, norm = workspace:FindPartOnRayWithIgnoreList(newRay, ignoreList)

You will probably want to run that continuously so that it updates as you move your mouse or the world moves. I would recommend putting it inside a function that is bound to renderstep.

Edit: Fixed a typo that would cause the code to error.

5 Likes

I’ve got a custom mouse object on GitHub that uses raycasting.

@Intended_Pun Feel free to grab a copy and modify it so that you can retrieve the surface normal, all the other work is done for you. I might consider adding those extra FindPartOnRay returns as features of the mouse target system too.

EDIT: Added it under the RbxMouse.Normal property real quick. Right now it’s in the dev branch because I haven’t tested it yet.

3 Likes

That’s not working at all. This is what I’m doing. The model doesn’t anywhere that I can see.

game:GetService("RunService").RenderStepped:connect(function()
   ignoreList = game.Workspace:WaitForChild("BaseStore"):GetChildren()
   mouseRay = mouse.UnitRay
   newRay = Ray.new(mouseRay.Origin, mouseRay.Unit.Origin*MAX_PLACEMENT_DISTANCE)
   target, pos, norm = workspace:FindPartOnRayWithIgnoreList(newRay, ignoreList)--]]
end)

mouse.Move:connect(function()
   if item then
	 local endPos = pos + (norm * item.Primary.Size)
	 item:SetPrimaryPartCFrame(CFrame.new(endPos))
   end
end)

Sorry! The ray API confused me. Replace mouseRay.Unit.Origin with mouseRay.Direction.unit

Edit: Attached is the placefile that I used to test and figure out what the problem was. You can use it for an example if you’d like.

DragModelExample.rbxl (13.4 KB)

7 Likes

That kind of fixed it. Mine is still really bad though when I compare it with the example. I’ll probably work on it some when I have the time. Otherwise it’s awesome. Thanks for all the help

1 Like