luaroblox

Clamp a part within bounds (Roblox)


I am making a building system for my game, for which I need to make a clamping function.

This function should clamp the hit position of the player´s mouse for a part following the mouse to stay within specific bounds (the player´s baseplate) so it doesn´t clip out on any side in any rotation.

My problem here, is that I don´t know how to execute this. I´ve prepared some variables for myself (such as the part´s and baseplate´s Look- and RightVectors and their negatives) but I don´t exactly know how to use them.

I am thinking about:

  1. getting the hit position relative to the baseplate

  2. clamping that position along x and z so that the max value is (baseplateSize-(partSize/2))

This would work, but only if the part couldn´t rotate, and even so could work on only most sides.

My current progress:

function clamp(hit,obj:Model)
    local part = obj.PrimaryPart
    local partSize = part.Size/2
    
    local partFront = part.CFrame.LookVector
    local partBack = -partFront
    local partRight = part.CFrame.RightVector
    local partLeft = -partRight
    
    local plateFront = platePart.CFrame.LookVector
    local plateBack = -plateFront
    local plateRight = platePart.CFrame.RightVector
    local plateLeft = -plateRight
    
    return CFrame.new()
end

(I really don´t know how to write proper StackOverflow questions, please ask me for more context/information if needed)


Solution

  • I found an easier way to do this.

    function clamp(obj:Model,cf:CFrame)
        local part = obj.PrimaryPart
        local partSize = part.Size/2
        local plateSize = platePart.Size/2
        
        local localCf = platePart.CFrame:ToObjectSpace(cf)
        
        local _,ry,_ = cf:ToOrientation()
        local Y = math.deg(ry)+180
        
        if math.round(Y/90)%2 == 0 then
            maxX = plateSize.X-partSize.X
            maxZ = plateSize.Z-partSize.Z
        else
            maxX = plateSize.Z-partSize.Z
            maxZ = plateSize.X-partSize.X
        end
        
        local x = math.clamp(localCf.X,-maxX,maxX)
        local z = math.clamp(localCf.Z,-maxZ,maxZ)
        
        local newCf = platePart.CFrame:ToWorldSpace(CFrame.new(x,0.5+partSize.Y,z)) *  cf.Rotation
        
        return newCf
    end
    

    In this script, the maximum position along each axis of the plane is based on which axis of the part to be clamped faces the same way as the plate´s.

    If the X axes differentiate by 90°, it means that Z of the part faces the same/opposite way as the X of the plate. Example of X and Z axes of plate and part facing different directions