Hello! I am working on an update for my module Placement Service (a placement system module). I am facing a issue with the module on rotated plots. The collision system detects collisions even if the model being placed is on the grid units adjacent to another model (only if the placed model and plot are rotated). What doesn’t make sense to me is it doesn’t happen as often with smaller grid units (1, 2), and it doesn’t happen over the entire part. I don’t know why this is happening as from my testing, there should be no collision even though it’s detecting something. My best guess is that somehow the placed part is being slightly rotated which would make it so only a portion of the model detects collisions, but I’ve compared the rotation of the placed model and the one being placed and it matches. There are no other objects that are interfering with the collisions either. The server code doesn’t change the position or rotation on placement so there is no issue there either. Although both the server and client detect a collision from my testing.
Here is a video showing the issue:
Maybe I’m just missing something, so here is my code where I think the issue is:
Here is the collisions function I am using
local function checkHitbox()
if object and collisions then
if range then
setCurrentState(5)
else
setCurrentState(1)
end
local collisionPoints: {BasePart} = workspace:GetPartsInPart(hitbox)
-- Checks if there is collision on any object that is not a child of the object and is not a child of the player
for i = 1, #collisionPoints, 1 do
if collisionPoints[i].CanTouch and not collisionPoints[i]:IsDescendantOf(object) and not collisionPoints[i]:IsDescendantOf(character) and collisionPoints[i] ~= plot then
setCurrentState(3)
if preferSignals then
collided:Fire(collisionPoints[i])
end
break
end
end
return
end
end
Here is where the position is calculated:
-- Calculates the position of the object
local function calculateItemLocation(last, final: boolean): CFrame
local x: number, z: number
local cx: number, cz: number
local sizeX: number, sizeZ: number = primary.Size.X*0.5, primary.Size.Z*0.5
local finalC: CFrame
if not currentRot then
sizeX = primary.Size.Z*0.5
sizeZ = primary.Size.X*0.5
end
if moveByGrid then
cx = sizeX - floor(sizeX/GRID_UNIT)*GRID_UNIT
cz = sizeZ - floor(sizeZ/GRID_UNIT)*GRID_UNIT
else
cx = sizeX
cz = sizeZ
end
local cam: Camera = workspace.CurrentCamera
local camPos: Vector3 = cam.CFrame.Position
local unit: Ray
local ray
local nilRay
if isMobile then
ray = workspace:Raycast(camPos, cam.CFrame.LookVector*maxRange, raycastParams)
nilRay = camPos + cam.CFrame.LookVector*(maxRange + plot.Size.X*0.5 + plot.Size.Z*0.5)
else
unit = cam:ScreenPointToRay(mouse.X, mouse.Y, 1)
ray = workspace:Raycast(unit.Origin, unit.Direction*maxRange, raycastParams)
nilRay = unit.Origin + unit.Direction*(maxRange + plot.Size.X*0.5 + plot.Size.Z*0.5)
end
if ray then
x, z = ray.Position.X - cx, ray.Position.Z - cz
if stackable then
target = ray.Instance
else
target = plot
end
else
x, z = nilRay.X - cx, nilRay.Z - cz
target = plot
end
y = calculateYPos(plot.Position.Y, plot.Size.Y, primary.Size.Y)
-- Changes y depending on mouse target
if stackable and target and (target:IsDescendantOf(placedObjects) or target == plot) then
if ray and ray.Normal then
if not isMobile and cframe(ray.Normal):VectorToWorldSpace(Vector3.FromNormalId(Enum.NormalId.Top)):Dot(ray.Normal) > 0 then
y = calculateYPos(target.Position.Y, target.Size.Y, primary.Size.Y)
elseif isMobile then
y = calculateYPos(target.Position.Y, target.Size.Y, primary.Size.Y)
else
y = ray.Instance.Position.Y
end
end
end
-- Clamps y to a max height above the plot position
y = clamp(y, initialY, maxHeight + initialY)
local pltCFrame: CFrame = plot.CFrame
if moveByGrid then
-- Calculates the correct position
local rel: CFrame = pltCFrame:Inverse()*cframe(x, 0, z)*cframe(cx, 0, cz)
local snappedRel: CFrame = snapCFrame(rel)*cframe(cx, 0, cz)
if not removePlotDependencies then
snappedRel = bounds(snappedRel, sizeX, sizeZ)
end
finalC = pltCFrame*snappedRel
else
finalC = pltCFrame:Inverse()*cframe(x, 0, z)*cframe(cx, 0, cz)
if not removePlotDependencies then
finalC = bounds(finalC, sizeX, sizeZ)
end
finalC = pltCFrame*finalC
end
-- For placement or no intepolation
if final or not interpolation then
return (finalC*cframe(0, y - plot.Position.Y, 0))*anglesXYZ(0, rot*pi/180, 0)
end
return (finalC*cframe(0, y - plot.Position.Y, 0))*anglesXYZ(0, rot*pi/180, 0)*calcAngle(last, finalC)
end
Here is a demo place to test the issue out or see the full source code of the module used (and anything else that could be causing this issue):
placementbug.rbxl (71.5 KB)
(make sure when testing to rotate the object)
Thank you to all who help, it is greatly appreciated. If I learn any new information, I’ll update this post with that.
Anyways, thanks!
