I wasn’t a big fan of the default DragDetector styles, I was hoping they would have a more Lumber-Tycoon-2-style drag option but the closest was TranslateViewPlane, which still wasn’t ideal.
So I put some constraints inside the part that help “glue” it to the player properly, along with some custom cosmetics. Would love to hear anyone’s thoughts on this system, how to improve it, etc. (I am novice coder).
Right now the only thing I don’t like about this system is how the part seems to “lag” (not literally but physically) when the player walks either directly towards or away from it, even with the AlignPosition set to max responsiveness/force/velocity. Not sure how to improve that.
I turned it into a ServerScriptService handler by distributing the click detector and constraints via a for loop, and put the functions in there too. Now i can just tag a part or model with “Grab” (and assign it a primary part if it’s a model) and it’s pick-up-able.
local collectionService = game:GetService("CollectionService")
local one = script.DragDetector
local two = script.AlignOrientation
local three = script.AlignPosition
for i, PartOrModel in collectionService:GetTagged("Grab") do
local clicker = one:Clone()
local orient = two:Clone()
local posit = three:Clone()
local att = Instance.new("Attachment")
att.Name = "grabAtt"
local goal = nil
local distance = 8
local mainPart = PartOrModel
if PartOrModel:IsA("Model") then
mainPart = PartOrModel.PrimaryPart
end
clicker.Parent = PartOrModel
orient.Parent = PartOrModel
posit.Parent = PartOrModel
att.Parent = mainPart
orient.Attachment0 = att
posit.Attachment0 = att
clicker.DragStart:Connect(function(plr, ray, viewFrame, hitFrame, BP, other, key)
goal = plr.Character.Head.FaceFrontAttachment
att.WorldOrientation = goal.WorldOrientation
att.WorldPosition = hitFrame.Position
orient.Attachment1 = goal
distance = (att.WorldPosition - goal.WorldPosition).magnitude
mainPart.Massless = true
posit.Position = mainPart.Position
posit.Enabled = true
end)
clicker.DragContinue:Connect(function(plr, ray, viewFrame, other, key)
local newFrame = CFrame.new(goal.WorldPosition, goal.WorldPosition + ray.Direction.Unit)
newFrame = newFrame * CFrame.new(0, 0, (-distance - 1))
posit.Position = newFrame.Position
end)
clicker.DragEnd:Connect(function(plr)
mainPart.Massless = false
orient.Attachment1 = nil
posit.Enabled = false
end)
end
Same clickdetector and constraint settings, but parented to the script in ServerScriptService instead of individual parts in the workspace