Problem with grid snapping and CFrame.lookAt()

Hey there! :wave:

I’m making a road-building system, but I’ve run into an issue with grid snapping and CFrame.lookAt(). Firstly, I’d like to place the start segment of the road, then rotate it towards the end segment. The end segment should also rotate towards the start. This is my code so far:

local xGrid = 4

local function gridSnap(pos)
	return Vector3.new(
		math.floor(pos.X / xGrid + 0.5) * xGrid,
		pos.Y,
		math.floor(pos.Z / xGrid + 0.5) * xGrid
	)
end

-- (getting the start position...)

while task.wait() do
	local ray = mouseRay()

	if ray then
		local endPos = gridSnap(ray.Position)
		roadEnd.Parent = game.Workspace

		roadEnd:PivotTo(CFrame.lookAt(endPos, startPos, Vector3.new(0, 0, 1)))

		roadStart:PivotTo(CFrame.lookAt(startPos, endPos, Vector3.new(0, 0, 1)))
	end
end

If the snapping is enabled for the start segment and disabled for the end segment, the system seems to work:

If the snapping is enabled for both the start and end segments, this happens:

The printed position of the actual model seems to be correct, though when I click on the parts within the model, the position is completely off:

If anybody has ideas on why this is happening, please let me know! Thank you!

2 Likes

I’m not too sure what is going on here. I ran your script and the snapping work fine for both. Maybe you should check the endpos and startpos

1 Like

Here are some other things to consider:

  1. Set the parent of the end road at the last line of the loop
  2. The ray cast(if not set up properly) could be picking up the position of the start road
  3. Ensure the position of start and end are not the same
1 Like

Maybe this will help..

local xGrid = 4

local function gridSnap(pos)
    return Vector3.new(
        math.floor(pos.X / xGrid + 0.5) * xGrid,
        pos.Y,  --keep original Y for terrain/height
        math.floor(pos.Z / xGrid + 0.5) * xGrid
    )
end

while task.wait() do
    local ray = mouseRay()
    if ray then
        local snappedEndPos = gridSnap(ray.Position)
        local orientation = CFrame.lookAt(snappedEndPos, startPos)
        
        orientation = CFrame.new(orientation.Position) * CFrame.fromMatrix(
            Vector3.new(0, 0, 0), 
            orientation.LookVector, 
            Vector3.new(0, 1, 0) 
        )
        
        roadEnd:PivotTo(orientation)
        roadStart:PivotTo(CFrame.lookAt(startPos, snappedEndPos))
    end
end

Looks like endPos snaps to grid and startPos also snaps to grid.
Possibly both points are jumping suddenly, causing problems.

2 Likes

Your problem is that endPos ≠ startPos because when you call CFrame.lookAt(), you’re essentially saying to look at itself, which causes it to go crazy and spit out that large number. My recommendation is if they are equal, don’t call lookAt().

Here is a fixed version of your script:

local xGrid = 4

local function gridSnap(pos)
	return Vector3.new(
		math.floor(pos.X / xGrid + 0.5) * xGrid,
		pos.Y,
		math.floor(pos.Z / xGrid + 0.5) * xGrid
	)
end

-- (getting the start position...)

while task.wait() do
	local ray = mouseRay()

	if ray then
		local endPos = gridSnap(ray.Position)
		roadEnd.Parent = game.Workspace
		if startPos == endPos then continue end -- if positions are the same, do nothing

		roadEnd:PivotTo(CFrame.lookAt(endPos, startPos, Vector3.new(0, 0, 1)))

		roadStart:PivotTo(CFrame.lookAt(startPos, endPos, Vector3.new(0, 0, 1)))
	end
end
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.