Snap Building System

I want to achieve a building system that allows the player to move a part that clips to other objects. Here’s what’s going on:

note: the hinge is to represent the front face

The issue with this is that when the object goes from the right side to the top side, it turns to the front instead of continuing to face right.

Here is the lua code I have that achives what I showed above:

local runService = game:GetService("RunService")
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local demoModel = script.Teddy

demoModel.Parent = workspace

function MoveToMouse(Model)	
	if mouse.Target then
		-- cast our ray and get our normal, which is a unit vector
		--creates a ray of length 1 that points in the camera's look vector and in the position on the screen
		local unitRay  = workspace.CurrentCamera:ScreenPointToRay(mouse.X, mouse.Y, 1) --origin, Vector3.new(0, -1, 0));
		--makes a new ray that is the same as the unit ray but with length 1000
		local ray = Ray.new(unitRay.Origin, unitRay.Direction * 1000)
		--normal is the look vector(I think) of the surface that the ray hit
		local hit, position, normal = workspace:FindPartOnRay(ray, Model)
		local hitCFrame = CFrame.new(position, position+normal)
		
		demoModel:SetPrimaryPartCFrame(hitCFrame *CFrame.Angles(-math.rad(90),0,0))
	end;
end

runService.RenderStepped:Connect(function()
	MoveToMouse(demoModel)
end)

Here is the file of the place I used to make the gif:
MoveSystem.rbxl (45.2 KB)

Here’s the post that I got most of the code from: Placement System For Wall Objects - #17 by sunyesta

I’m still kind of new to CFrames so maybe that’s why I can’t figure this out.
Anyways, thanks for the help in advance :slight_smile:

It is because you are using a normal vector, which is the face direction of the object, look here of explanation: Explanation of Surface Normal?. You would need to do this:

local hitCFrame = CFrame.new(position, somePosInFront)

Instead of:

local hitCFrame = CFrame.new(position, position + normal)
1 Like

I still want the object to snap to the normal. The issue is that I the object should continue to face right if it was facing right when it snapped to the side:

Here is an example of what I want:
bear pre ---->final good

bear pre2 ---->final current

This is what is happening:
bear pre---->final current

So basically, if the bear should copy it’s previous up vector if it’s up vector’s direction is 1. (I think)

set its face direction to a value that doesn’t change

1 Like

I’m confused on how make sure that only one element of the look vector doesn’t change

If I’m understanding this right, you’re wanting the orientation of the model to stay the same. You’re just wanting to change the positioning of it? If so, why not just do:

demoModel:SetPrimaryPartCFrame(CFrame.new(hitCFrame.p)*CFrame.Angles(-math.rad(90),0,0))

edit: oops, after re-reading I realized that’s not what you’re wanting to do at all. Sorry.

1 Like
local hitCFrame = CFrame.new(position, bear.CFrame.LookVector)

It does this:

local hitCFrame = CFrame.new(position, position + Vector3.new(0,0,1))
2 Likes

It still doesn’t work :frowning:
If you want, I attached the file I’m working with to the topic so you can test stuff out easily

I feel like I need to do something like:

if normal.Y == 1 then
	--change hitCFrame so it doesn't change the direction of the model
end

I just don’t really know how to do the thing inside the if statement

.lookVector exist for this

set the cframe to the normal but have it face the lookvector of the part
if it’s looking down like the gif posted above then I’m not sure that’s the actual front of the part then, or you’re not doing something right

I think this is what you meant?

local hit, position, normal = workspace:FindPartOnRay(ray, Model)
local hitCFrame = CFrame.new(position, hit.CFrame.LookVector)		

It gave me the same result as this gif:

you’re not implementing the lookvector with the face that you hit. Mouse.TargetSurface and Rays both give you the normal which you can then determine how to use the lookVector. -rightVector, upVector, etc

I thought I was doing that in this line:

local hitCFrame = CFrame.new(position, position+normal)
1 Like

Oh my bad, I think you just need to setup some logic. Detect what face it is on, and if is on face 1 through 4, 5 being top, 6 being bottom,set the part’s cframe to the position and the normal, but when you go over the top (5) set the cframe but keep the same rotation

3 Likes

Yes, you’re right. I just realized that I needed to create a new building algorithm for cubes to do just that. Thanks for the help! :slight_smile:

1 Like