Hello developers! I were making a placement module for community resources and I get an error/glitch, I’m trying to clamp a CFrame to a canvas part and I made it but the problems come when I need to replicate that in rotated parts, I used math.sin and I got a good result, but I have a problem which I can’t explain so I’ll upload a video of the problem
Here is the vid
If the rotation is 90, 225, 270, or 315 the model gets out of the bounds
The code that clamps the CFrame it’s this:
local function clampToBounds(position, size, bounds)
local PosX = position.X
local PosZ = position.Z
local value = rotation
PosX = math.clamp(PosX, ((bounds.Position.X - bounds.Size.X/2)+(size.X/2))+math.sin(value), ((bounds.Position.X + bounds.Size.X/2)-(size.X/2))-math.sin(value))
PosZ = math.clamp(PosZ, ((bounds.Position.Z - bounds.Size.Z/2)+(size.Z/2))+math.sin(value), ((bounds.Position.Z + bounds.Size.Z/2)-(size.Z/2))-math.sin(value))
return Vector3.new(PosX, position.Y, PosZ)
end
That’s not really what you would use that trig function for, and a better solution is to determine how much the object is over bounds at its boundaries. Then push it back by that much (before it’s even placed).
Example place file attached for you to look at. The code is also attached if you don’t want to look at the place file. Video also below.
local part: BasePart, base: BasePart = workspace.Part, workspace.base
local function getCornerPositions(part)
return {
(part.CFrame:pointToWorldSpace(Vector3.new(part.Size.X/2,0, part.Size.Z/2)));
(part.CFrame:pointToWorldSpace(Vector3.new(part.Size.X/-2,0, part.Size.Z/2)));
(part.CFrame:pointToWorldSpace(Vector3.new(part.Size.X/2,0, part.Size.Z/-2)));
(part.CFrame:pointToWorldSpace(Vector3.new(part.Size.X/-2,0, part.Size.Z/-2)));
}
end
local function getVectorOutOfBounds(corner, base): Vector3
local objectSpaceCorner: Vector3 = base.CFrame:pointToObjectSpace(corner)
local roundedCornerX: number = math.round(objectSpaceCorner.X * 10) / 10
local roundedBoundsX: number = math.round(base.Size.X/2 * 10) / 10
local roundedCornerZ: number = math.round(objectSpaceCorner.Z * 10) / 10
local roundedBoundsZ: number = math.round(base.Size.Z/2 * 10) / 10
local adjustmentVector: Vector3 = Vector3.new()
if (math.abs(roundedCornerX) > roundedBoundsX) then
adjustmentVector += Vector3.new(math.abs(objectSpaceCorner.X) - base.Size.X/2,0,0) * (objectSpaceCorner.X > 0 and -1 or 1)
end
if (math.abs(roundedCornerZ) > roundedBoundsZ) then
print(objectSpaceCorner.Z)
adjustmentVector += Vector3.new(0,0,math.abs(objectSpaceCorner.Z) - base.Size.Z/2) * (objectSpaceCorner.Z > 0 and -1 or 1)
end
return adjustmentVector
end
game:GetService("RunService").Heartbeat:Connect(function()
local corners = getCornerPositions(part)
local isPartOutOfBounds: bool = false
local adjustmentDistance: Vector3 = Vector3.new()
-- Analyze all corners
for _, cornerPosition in pairs(corners) do
local vectorOutOfBounds: Vector3 = getVectorOutOfBounds(cornerPosition, base)
if (vectorOutOfBounds ~= Vector3.new()) then
adjustmentDistance += vectorOutOfBounds
isPartOutOfBounds = true
end
end
if (isPartOutOfBounds) then
part.CFrame = part.CFrame + adjustmentDistance
end
end)
The example uses the Heartbeat which is a bit jumpy, so you’d want to connect the code to an event you have or something.
It didn’t work, I added it to my clamp function and I got a glitchy thing, the block just keeps teleporting out of the bounds and then comes back to the bounds
I think I’ll keep using the old function, I fixed the problem at 90% using math.abs
local offset = math.abs(math.sin(value % math.pi))
If the axis is 90 degrees the part doesn’t fit the bounds correctly but I can skip that