maybe raycast from part origin (center) to the edge points of the part
local TopMiddle = part.CFrame + (part.CFrame.UpVector * part.Size.Y/2)
local RightMiddle = part.CFrame + (part.CFrame.RightVector * part.Size.X/2)
local BottomMiddle = part.CFrame - (part.CFrame.UpVector * part.Size.Y/2)
local LeftMiddle = part.CFrame - (part.CFrame.RightVector * part.Size.X/2)
starting from the center, adding half of the size will bring you to the edge
placement.rbxl (33.8 KB)
local mouse = game.Players.LocalPlayer:GetMouse()
local ghost = Instance.new("Part")
ghost.Size = Vector3.new(5, 10, 1)
ghost.Transparency = 0.6
ghost.Anchored = true
ghost.CanCollide = false
ghost.Parent = workspace
mouse.TargetFilter = ghost
game:GetService("UserInputService").InputEnded:Connect(function(InputObject, Processed)
if InputObject.KeyCode == Enum.KeyCode.R then
ghost.Orientation = ghost.Orientation + Vector3.new(0, 5, 0)
end
end)
local visParts = {}
while wait() do
if mouse.Hit then
for _, visPart in pairs(visParts) do
visPart:Destroy()
end
ghost.Position = mouse.Hit.Position + Vector3.new(0, ghost.Size.Y/2, 0)
local CFrames = {
ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2),
ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.X/2),
ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2),
ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.X/2)
}
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {ghost}
local hit = false
for index, cf in pairs(CFrames) do
local visPart = Instance.new("Part")
visPart.Anchored = true
visPart.CFrame = cf
visPart.Size = Vector3.new(1,1,1)
visPart.Name = index
visPart.CanCollide = false
visPart.Transparency = .6
visPart.Color = Color3.fromRGB(60, 1, 255)
visPart.Parent = ghost
table.insert(visParts, visPart)
local r = workspace:Raycast(ghost.Position, cf.Position - ghost.Position, raycastParams)
if r then
if r.Instance then
hit = true
end
end
ghost.Color = hit and Color3.fromRGB(255, 0, 4) or Color3.fromRGB(0, 255, 106)
end
end
end
you can add more points for accuracy:

local CFrames = {
ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2),
ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.X/2),
ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2),
ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.X/2)
}
for i = (ghost.Size.Y/2)/5, ghost.Size.Y/2 do
table.insert(CFrames, ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, i, 0))
table.insert(CFrames, ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, -i, 0))
table.insert(CFrames, ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, i, 0))
table.insert(CFrames, ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, -i, 0))
table.insert(CFrames, ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2) + ghost.CFrame.RightVector * i/2)
table.insert(CFrames, ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2) - ghost.CFrame.RightVector * i/2)
table.insert(CFrames, ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2) + ghost.CFrame.RightVector * i/2)
table.insert(CFrames, ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2) - ghost.CFrame.RightVector * i/2)
end
these scripts are rough concepts, re-write them yourself