Announcing DragDetectors!

Hey @PrinceTybalt ,
On the tycoon how can i get all dropper parts being spawned to allow the tycoon carrying? Reason why i’m asking is that I want droppers to be spawn earlier and then they can upgrade the base to get conveyors and burners but want them to carry to the power station first off? Here is my droppers script:

local dropsFolder = game:GetService("ServerStorage").Drops
local Debris = game:GetService("Debris")
local Players = game:GetService("Players")

local Dropper = {}
Dropper.__index = Dropper

function Dropper.new(tycoon, instance, ownerPlayer)
	local self = setmetatable({}, Dropper)
	self.Tycoon = tycoon
	self.Instance = instance
	self.Rate = instance:GetAttribute("Rate")
	self.DropTemplate = dropsFolder[instance:GetAttribute("Drop")]
	self.DropSpawn = instance.Spout.Spawn
	self.OwnerPlayer = ownerPlayer  -- This assumes you're passing the player who owns the dropper
	self.DebrisTome = 1800

	return self
end

function Dropper:Init()
	coroutine.wrap(function()
		while true do
			self:Drop()
			wait(self.Rate)
		end
	end)()
end

function Dropper:Drop()
	local replicatedStorage = game:GetService("ReplicatedStorage")

	local drop = self.DropTemplate:Clone()
	drop.Position = self.DropSpawn.WorldPosition
	drop.Parent = workspace  -- Parent the drop to workspace or a specific folder within workspace

	if drop:IsA("BasePart") then
		drop:SetNetworkOwner(self.OwnerPlayer)  -- Set the network owner to the owner player
	end

	-- Add the LiftAndCarry_Physical_ClientScript to the drop
	local existingLocalScript = replicatedStorage:FindFirstChild("LiftAndCarry_Physical_ClientScript")
	if existingLocalScript then
		local clonedLocalScript = existingLocalScript:Clone()
		clonedLocalScript.Parent = drop
	end

	-- Add the DragDetector to the drop
	local existingDragDetector = replicatedStorage:FindFirstChild("DragDetector")
	if existingDragDetector then
		local clonedDragDetector = existingDragDetector:Clone()
		clonedDragDetector.Parent = drop
	end

	Debris:AddItem(drop, self.DebrisTime)
end

return Dropper

I’ve tried the same method for my trees but they dont seem to be draggable for some reason.

1 Like

Try to test it by launching roblox and joining your experience.
If it does work there, try disabling plugins, they may interrupt dragging, which i still don’t clearly understand why.
If it did not help, then you need to search for any errors or break points in script.

1 Like

@MonsterStepDa based on past discussions, I assume this is working for some objects already? So there is something different about your trees than that other types of objects? If you want to expand the description of the problem and what’s different about the trees more fully, or post a test world ,or send me one in a message I can take a look, but from what I know so far, I can’t help.

1 Like

@PrinceTybalt
A major bug seems to be apparent with the DragDetectors. I submitteda report to the bug team, but I figure it might even be faster to report it here to you directly as well.

Issue Description:

When a Drag Detector is Disabled while being used (Dragged) by a player. Any other player will be unable to use that drag detector, no matter what you do or try.

:arrows_counterclockwise: Reproduction:

Repo is rather simple.

  1. Add a functioning DragDetector to an object.
  2. Have one player drag it.
  3. Disable the DragDetector while the player is dragging it.
  4. Enable the DragDetector.
  5. Attempt to have any other player try to drag the object. It will not be possible.
1 Like

Hello @LadyAka thanks for reporting this. I have a similar test I run that doesn’t exhibit this problem.
This little script is working okay:

local dragDetector = script.Parent

do
	dragDetector.DragStart:Connect(function()
		-- start 2 second timer
		wait(2)
		print("Disabling DragDetector")
		dragDetector.Enabled = false
		wait(.1)
		print("Enabling DragDetector")
		dragDetector.Enabled = true
	end)
	dragDetector.DragEnd:Connect(function()
		print("Drag End")
	end)
end

So I need some more details to figure out what is broken for you.
[1] does your DragDetector have runLocally set to true or false (the default)? I assume it’s false since you are talking about multiple players dragging the same object.
[2] You said you are disabling the DragDetector while the player is dragging. How are you disabling the DragDetector? Through a script?
[3] When you enable the DragDetector, is this also through a script? Do you enable the DragDetector while the first player is still dragging, or sometime later?

If you can post a simple test world that shows the problem that would be even better.

1 Like

@PrinceTybalt I need help… again :frowning: Sorry for bugging you but how would I make this https://www.youtube.com/watch?v=jP3y9Wi0o_k

Into this? https://youtu.be/lVSyJOhDYIk

A few things first, here are my properties

And how would I make it not go so far away? What you replied did not make sense sorry. :frowning:
-xxoof_oofoofxx

2 Likes

@xxoof_oofoofxxALT for the behavior you want, you should use the style from the Lift & Carry Game. You can download a copy of that game. There are two variations, one moves geometric style and the other physical style. They require a special script, this behavior is not baked into the DragDetector alone.
You can also grab just the two models separately:
Lift-And-Carry-Geometric or Lift-And-Carry-Physical.
To use these you are going to need to need to put all the children of the part from that model below your own part.

3 Likes

Thank you! But I have a question; I was studying the scripts and found this:
Screenshot 2023-10-30 160304
Why is there an error, or is that supposed to be there?

2 Likes

@xxoof_oofoofxxALT Oh, hurray! Since I started working here, they deprecated Blacklist and Whitelist in favor of Exclude and Include.
I’ve fixed the scripts and uploaded the game/models again. Thanks.

1 Like

I am quite unsure about how this will work on touchscreen devices. Like if i drag something with one finger on a phone and place another finger on the screen. Will it just suddenly appear at the other finger as this is the case with most feature which includes moving objects with mouse before this update.

1 Like

@Testbot379 DragDetector policy is that only one player or finger may drag it at a time.
So once you touch a DragDetector with one finger, that finger ‘owns’ the drag until it lets go. The second finger will have no effect. (At some point we may add the ability for two players or fingers to drag at the same time, but if we do that it will be more like pushing a brick from both ends at once, without any jump. In the interim, you can get a similar effect by welding two separate handles-with-dragdetectors to the same object, allowing two players to move it together)

Note that you CAN move multiple objects with individual fingers simultaneously, so long as they contain separate DragDetectors

2 Likes

Hello again @LadyAka,

We were able to reproduce your bug. What I failed to grasp was that after enable/disable, the first player could still drag the object, but OTHER players could not! @DeFactoCepti helped me understand.
He has checked in a fix for the issue, and if all goes well, the fix should be live late next week.

thanks so much for reporting this!

4 Likes

Thank you. sorry for checking late, I was really busy this week. I was about to make a repo file but I’m glad you were able to figure it out!

3 Likes

Little info about a typo you made in one of the scripts on DragDetectors TestWorld 2 - Roblox

Script: workspace.ConstraintAndScriptableDragStyleExamples.ConstraintExampleUtils
Line: 18
Reason: Too many end.

2 Likes

Could someone help me in my case?


EDIT: problem solved!

1 Like

I have this current setup:

Setup in workspace

image

DragDetector properties

LocalScript parented to StarterPlayerScripts

local Detector: DragDetector = workspace:WaitForChild("TestPartDrag"):WaitForChild("DragDetector") :: DragDetector

Detector:AddConstraintFunction(1000, function(ProposedMotion: CFrame): CFrame
    warn((CFrame.new(0, 0, 0) * ProposedMotion.Rotation).Position)
    return CFrame.new(0, 0, 0) * ProposedMotion.Rotation
end)

Detector:GetPropertyChangedSignal("DragFrame"):Connect(function(): ()    
    print(Detector.DragFrame.Position)
end)

Result

Why does my DragFrame have a position, whereas I only send the ProposedMotion.Rotation (with a blank position in another CFrame)?

Repro place: repro.rbxl (54.9 KB)

I noted that, the higher the part is height-wise, the “higher” it’ll spin around

I may have some misconceptions in CFrame understanding, but I think I am correct in this example still


This is what made me think my logic is right by the way.

@PrinceTybalt i’ve messaged you and sent a friend request so you can have a look at my place.

2 Likes

Thanks for letting me know. It’s all fixed now.

3 Likes

@Varonex_0 it will take me a little while to work up a full answer with examples, but the crux of the issue is that the frames passed in and out of the constraint function are motion expressed in worldspace, not reference space.

Since the object is away from the origin, a rotation matrix with no translation will orbit the object around the origin of the workspace. The extra translation is to put it back at the referenceInstance origin.

I will work up a proper example for how to, say, clamp the rotations in increments of 10 degrees and post it. It’s going. to involve [a] setting the referenceInstance of the dragDetector; otherwise that frame is based on the part and it’s going to rotate every time you finish a new drag [b] casting the incoming proposed motion to reference space [c] clamping the motion, and [d] casting the result back out into worldspace.

Gosh this sounds messy. Sounds like we should have an option for registering a constraint function that operates relative to the referenceFrame.

1 Like

I will test this out.

I am not a huge friend of vectorial spaces at all, that’s why your explanation still looks a bit hard to understand :sweat_smile:

I will work my way out still !

What I understood from the ProposedMotion you are receiving is that:

  • ProposedMotion.Position is the translation of the startCFrame.Position to the final theoretical position (let’s call it endCFrame.Position)
  • ProposedMotion.Rotation is the new rotation of the PVInstance you are moving.

That is why I was sending CFrame.new(0, 0, 0), because I did not want the DragFrame to receive any translation at all. I visualized it as an offset between the startCFrame.Positon and the theoretical endCFrame.Position. That’s what I saw from my tests.

Am I correct in my analogy? If not, please correct me. If yes, then why when I send a CFrame with Vector3.zero as the translation, with rotation, it does that?

I may have some huge misconceptions on CFrames, despite the fact I am completely working my way out in what I’m doing.


EDIT:

Made a test:

local Part: Part = workspace:WaitForChild("TestPartDrag")
local Detector: DragDetector = Part:WaitForChild("DragDetector") :: DragDetector

Detector:AddConstraintFunction(1000, function(ProposedMotion: CFrame): CFrame
	warn("ProposedMotion:\t", ProposedMotion.Position, "\r")
	print("Custom:\t", ((CFrame.new(0, 0, 0)) * ProposedMotion.Rotation).Position, "\r")
	
	return ProposedMotion
end)

Indeed the ProposedMotion.Position isn’t blank. I cannot figure out why. Anyway, I’ll stick to the normal ProposedMotion since my Drag is only for orientation purposes.