Getting models to move up or down based on higher parts

Main Furnish Module

function furnish:StartPlacing(playersPlot, mouse, category, item)
	local itemClone = items[category.Name]:FindFirstChild(item):Clone()	
	
	for _, v in pairs(itemClone:GetChildren()) do
		if v:IsA('Part') then
			v.CanCollide = false
		end
	end
	
	itemClone.Parent = playersPlot.Camera
	
	local renderStepped	
	renderStepped = runService.RenderStepped:Connect(function()
		local cframe = placement(
			playersPlot.PrimaryPart,
			itemClone, 
			mouse.Hit.p, 
			var.Rotation
		)
		itemClone:SetPrimaryPartCFrame(cframe)
	end)
	
	table.insert(self.Connections, renderStepped)

	local click
	click = mouse.Button1Down:connect(function()
		for _, allModels in pairs(playersPlot.Purchases:GetChildren()) do
			if (itemClone.PrimaryPart.Position - allModels.PrimaryPart.Position).magnitude < 0.0001 then
				return
			end
		end

		click:Disconnect()
		renderStepped:Disconnect()
		place:FireServer(itemClone.Name, itemClone.PrimaryPart.CFrame)
		itemClone:Destroy()
	end)
	
	table.insert(self.Connections, click)
end

Placement calculations

function placement(basePart, model, position, rotation)
	local cframe, size = baseSize(basePart)

	local modelSize = CFrame.fromEulerAnglesYXZ(
		0, 
		rotation, 
		0
	)*model.PrimaryPart.Size
	
	modelSize = Vector3.new(
		math.abs(
			modelSize.x
		), 
		math.abs(
			modelSize.y
		), 
		math.abs(
			modelSize.z
		)
	)

	local lpos = cframe:PointToObjectSpace(position)
	local size2 = (
		size - Vector2.new(
			modelSize.x, 
			modelSize.z
		)
	)/2

	local x = math.clamp(
		lpos.x, 
		-size2.x, 
		size2.x
	)
	
	local y = math.clamp(
		lpos.y,
		-size2.y, 
		size2.y
	)

	local grid = var.Grid
	
	if grid > 0 then
		x = math.sign(x)*((math.abs(x) - math.abs(x)%grid) + (size2.x%grid))
		y = math.sign(y)*((math.abs(y) - math.abs(y)%grid) + (size2.y%grid))
	end
	
	return cframe*CFrame.new(x, y, -modelSize.y/2)*CFrame.Angles(-math.pi/2, rotation, 0)
end

return placement

Base size calculations

function baseSize(base)
	local canvasSize = base.Size

	local back = Vector3.new(0, -1, 0)
	local top = Vector3.new(0, 0, -1)
	local right = Vector3.new(-1, 0, 0)

	local cframe = base.CFrame*CFrame.fromMatrix(
		-back*canvasSize/2, 
		right, 
		top, 
		back
	)
	
	local size = Vector2.new(
		(
			canvasSize*right
		).magnitude, 
		(
			canvasSize*top
		).magnitude
	)

	return cframe, size
end

return baseSize

Model is flat with the grass, correct


Model sunk into the floor by 1 stud, not correct

As you can see, the model is flat with the grass, however it should move up 1 stud because of the floor and it being on the floor technically. The floors CanCollide is set to true

I am currently basing the base size on the grassed area, but is there a way to make it based on the actually floor of the house? The problem is the house floor isn’t just 1 part and isn’t just a rectangle or square.

1 Like