Placement System Issue

Hello!

I’m making a placement script right now, and the results are inconsistent. Sometimes, using half of the length works perfectly, but sometimes it has an odd offset.

– Notice, the barrel is pretty much perfect, but the vase is completely wrong

Here’s the script, I’m pretty certain that, in theory, it’s correct. Thanks for any help! :slight_smile:
– Note, CurrentItem is a Model!

local function castMouse()
	local mouseLocation = UserInputService:GetMouseLocation()
	local ray = camera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {character, circleFolder}
	return workspace:Raycast(ray.Origin, ray.Direction * 1000, params)
end

-- Function to update placement indicator position
local function updatePlacementIndicator()
	if placementIndicator then
		local mousePosition = getMouseWorldPosition()
		placementIndicator.Position = mousePosition

		local hrp = character:FindFirstChild('HumanoidRootPart')
		if currItem and hrp then
			local cast = castMouse()
			if cast and cast.Position then 
				
				local _, size = currItem:GetBoundingBox()
				local targetPos = mousePosition + Vector3.new(0, size.Y / 2, 0) -- This should fix all of it

				local newCF = CFrame.new(targetPos)
				newCF *= CFrame.Angles(math.rad(180), 0, 0)
				currItem:PivotTo(newCF)
			end	
		end
	end
end

I do agree that your script is most likely correct, however I think that the problem might stem from the :GetBoundingBox function as model bounding boxes aren’t always perfect. Especially if you have some sort of union, mesh or special shapes like cylinders and wedges.

Yeah, that’s probably the case. Do you recommend an alternative?

Maybe calculate the actual bottom of the model instead of relying on the center.

local function getModelBottom(model)
	local lowestY
	for _, part in ipairs(model:GetDescendants()) do
		if part:IsA("BasePart") then
			local partBottom = part.Position.Y - part.Size.Y/2
			if not lowestY or partBottom < lowestY then
				lowestY = partBottom
			end
		end
	end
	return lowestY
end

Then in your placement code:

local mousePos = getMouseWorldPosition()
local bottomY = getModelBottom(currItem)
local offset = currItem.PrimaryPart.Position.Y - bottomY
local targetPos = mousePos + Vector3.new(0, offset, 0)
currItem:PivotTo(CFrame.new(targetPos) * CFrame.Angles(math.rad(180),0,0))

Hopefully this should ensure the model always sits on the surface correctly, regardless of its shape, unions, or meshes.

I didn’t try this, but I found a different way which works pretty good! I created a part that mimics the bounding box and cframe, set it as the primary part, and used it for reference for placement.
– You’ll have to rotate it 180 on the Z axis every time for some reason, but now it works perfect!

Thanks for the help though!!!

Small angle offsets like 179 instead of 180 can often correct rounding or orientation errors caused by floating-point precision. Hard to actually tell the different from the player point of view in game. Also, perceived axes shift after rotation because local axes transform with the part’s orientation, so X and Y may swap roles relative to world space.. Especially if the part’s parent has its own rotation.

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