DragDetectors [Beta]

DragDetectors now will watch for changes in maxForce, maxTorque, responsiveness, and applyAtCenterOfMass, and consider them even while dragging. So you should be able to do those things now.

1 Like

Hi @0Tenth,

DragDetectors are scriptable in certain ways. What are you looking to do?

And it’s not clear to me what you mean by “they don’t seem to have default behavior.” What is the behavior you expect to see that you don’t?

First let me get clear on what you want to do.
Is it:
[a] when you click, rotate 90 degrees, then when you move the mouse, drag in a plane
[b] when you click, rotate 90 degress, then when you move the mouse, drag along a line in a direction that is also rotated 90 degrees
[c] something different?

The place is private now so I can’t record a video, but there was a DragDetector slingshot that when you pulled it back, it had multiple effects and sounds that played. When you released it would summon more effects and sounds. Also, when you dragged it there were multiple effects depending on how far you pulled it back. How would I achieve a effect like this?

Edit: Also, there was a cooldown for the DragDetector after dragging and releasing it.

Hi @0Tenth ,

There are a number of things that could classify as a slingshot, of course.
One example is the “Pull/Release To Fire” demo in DragDetectors Test World 1

Another is this self-yeeting slingshot I’ve been putting together for an upcoming instrutional video on the dev forum:

SelfYeetingSlingshot.rbxl (59.1 KB)

If you want to add effect that trigger depending how far you pull it back, you’ll want to watch the numbers in DragDetector.DragFrame.Position using a propertyChanged callback, and trigger your effects when number pass certain thresholds.

there’s an example of how to watch numbers in the ParticleLineSlider script of DragDetectors TestWorld 2. Look for the GetPropertyChangedSignal, and how that callback utilizes DragDetector.DragFrame.Position.X

1 Like

We need a way to detect if a DragDetector is being currently used and by who without relaying on Drag events, something similar to Seat’s Occupant. I may make a detailed feature request for this.

@vfx_1 Can you accomplish what you need with the new permission policy API?
This is a recent addition.
if you change the DragDetector.PermissionPolicy to Enum.DragDetectorPermissionPolicy.Scriptable,
you can then set a method that is invoked each time the dragDetector is clicked or moved using SetPermissionPolicyFunction. This function gets inputs of player and clickedPart. It returns true if the player may drag and false if not. If it returns false, the dragger will not move.

So if all you want to do is monitor, you can make a function that records the player and returns true.

Attached is a small game that prints the name of the player dragging each time dragdetector is clicked or moved.
PrintDraggingPlayerPermissionPolicy.rbxl (60.1 KB)

Here is the script used inside that game:

local dragDetector = game.Workspace.Part.DragDetector
dragDetector.PermissionPolicy = Enum.DragDetectorPermissionPolicy.Scriptable

dragDetector:SetPermissionPolicyFunction(function(player, part) 
	if player then
		print("player is", player.Name)
	else
		print("player is nil")
	end
	return true 
end)

I meant more like a new feature which could be a ReadOnly property indicating if the DragDetector is currently being used by someone and if so, set the variable to the using player. Basically the SeatPart Occupant functionality but on a drag detector. It would be useful to verify if the drag detector can be used at the moment or to avoid DragEnded not firing when it’s inside a DragStarted function and pressed very quickly which can cause stuff to stay at the state you don’t want it to be when not used.

@vfx_1
This is the first time that anybody’s made a request for this kind of API. I’d never say never, but this is not likely API that we are going to add.

First off, from an API point of view: in the future. we may make it so that multiple players or touch fingers can (optionally via API) move the same DragDetector at the same time. If we do this, then an ‘occupant’ property would no longer work, since there could be more than one. And we don’t have array properties to reflect multiple instances.
That said, we could conceivably add an API call to get this information that’s not necessarily a property
Or: Is it important that you know which player is using the dragDetector? Would an alternative read-only boolean property named “Active” meet your needs? This would be true while the dragger is being dragged, and false otherwise.

May I ask what about the current API forbids you from doing what you want to do? I mean it’s not as straightforward as your custom API request. You need to track your own variable, but why can’t it work?

Also, why are you against using the dragStart/dragContinue/dragEnd callbacks?
Because these can help you know if a dragDetector is being used at the moment using existing API.

But… it sounds like maybe you are having an event timing issue of some sort in terms of a dragEnd not firing, can you elaborate on the exact sequence/steps that gets you into a bad state?

Hello, thank you for a brief description of the planned functionality.

Of course it would be amazing! That’s what I thought about first. Just a simple boolean indicating if the drag detector is being used by someone at the moment or not, however for some reason I thought it would be better to have it solved like the Seat Occupant property but now I get it.

I made a safe input module which verifies all ClickDetector, DragDetector and ProximityPrompt actions on the server side, such as if player is in proper distance to fire the specific instance, if it’s enabled or additionally if there is a clear path between the player and the clickable instance. Also the .DragStart event for example will activate only when player hovers their mouse over the object first. However these checks take time and before the action is verified and the code which is supposed to run after all checks on .DragStart may run when player is not dragging anymore. So in this case I could easily check if player is still dragging the object and if so, add a one time .DragEnded connection, if no, do nothing.

The point of the whole thing is to provide a safe non exploitable environment for my game.

If any other details are needed, I can provide my code and desired functionality later.

@vfx_1 the PermissionPolicy API is supposed to help you make your game safe from exploits, that was one of our goals. So, for example, if you set the PermissionPolicy to Scriptable, your PermissionPolicy function must pass, otherwise the server will refuse to move the DragDetector.
It will only be called in the first place if nobody else is already dragging, and the player making the request is the first argument. So your method can return false if the player is not the proper distance to fire, or if there is not a clear path. This method will be called before any DragStart callback and will cut the whole process short if you return false.

I’d experiment and see whether this new feature helps you reach your goals somehow.

So tell me though… you have checks you run to see whether a player can drag. Do you perform those checks during dragStart? Before dragStart somehow? If you determine a player can’t or shouldn’t drag, how do you currently prevent them?

I will check if I can achieve that functionality with the PermissionPolicy API. I currently require a module which has DragStart, MouseHoverEnter etc. events. Does it work like DragStart will not be fired if player doesn’t pass the pre-check? I currently start performing the checks on MouseHoverEnter and then I unlock the DragStart and disconnect it on MouseHoverLeave. However as a backup it still wold be nice to have some sort of an .Active property indicating if the DragDetector is currently in use by someone. For example I believe with that way it could end up in one player being able to block the drag detector on purpose. I use DragDetectors to achieve a button functionality.

@vfx_1 I am going to add a potential task to add a .Active property to DragDetectors, but I can’t promise anything there.

In the meantime though I would really like to know how the PermissionPolicy works for you. It’s a new feature so feedback is important.

It should be the case that if your PermissionPolicy callback returns FALSE for a player, then DragStart will not be invoked. So you could perform your checks on mouseHoverEnter and set a value in, say, a map with a value per player, and then in your permission script you can quickly check against that map and return true or false. then on mouseHoverLeave you could set false for that player in your map.

I’d love to know if this helps you.

Thank you! I will still need it even when using the PermissionPolicy which I will explain below.

That is exactly what I did, however 3 things:

  1. .DragStart sometimes refuses to fire while being inside the PermissionPolicy function (I used it as .DragStart:Once(function()) but .DragEnd will fire (don’t know about .DragContinue as I don’t need to use it). So it is potentially a bug which I am not exactly able to specify when can happen.

  2. Because of that issue I tried making my code do the .DragStart action on PermissionPolicy check instead. However like with .DragStart the click can be so short that it won’t get to .DragEnd properly or just not become dragged after the PermissionPolicy check at all but run the code after all the checks I make which cause a significant delay at the same time causing my action being stuck on the entry state. Right here before running the code after my checks I could easily check if the DragDetector is still/became Active and if no, just void the rest, if yes, run it and add a .DragEnd event of what I want to be done after player is no longer holding the DragDetector (I do not make any checks for .DragEnd for obvious reasons).

  3. For unknown reasons the PermissionPolicy sometimes yields the code with an error “exception while signaling: Callbacks cannot yield” even though I am not yielding anything. I am also unable to specify when exactly as it happened like 3 times.

Can you upload a simple copy of your test world with the problem isolated so that I can try and reproduce your issues?
I’ll see whether they are bugs or not, and whether I can find you a workaround.

The phrase “DragStart sometimes refuses to fire while being inside the PermissionPolicy function” has me wondering, since DragStart is not something that happens within the permissionpolicy function. So maybe I can help.

I messaged you but looks like you didn’t see my message.

Sorry, I had a very serious issue come up with my cat on Friday (the illustrious Tybalt; my Roblox avatar is named after him, and the logo on my shirt is him wearing a crown) and I had to stop work early.

I am looking into your message today

2 Likes

I believe that the reason you are getting the “Callbacks cannot yield” message is because of your call to “Player:IsInGroup()”
If you bracket that call with print statements, you’ll see that the error occurs in that spot.
And if you add:
print(“before error”)
for i = 1, 100000 do
if Player:IsInGroup(4770885) then
print(“yes in group”)
end
end
print(“after error”)
Then you’ll maybe find it a little easier to tickle and you’ll see that the error occurs between those two prints.
The documentation on this method says something about caching results, and i was only able to invoke the error by playing the game, doing things in other windows, and coming back. So perhaps in the case where it finds the cache is dirty and needs to be reloaded, that in this case there is a yield involved?

Hi,
Sorry for not replying, I got quite busy irl. I will get back to you as soon as possible and reply to everything.

@vfx_1 Wait, this is not rl? uh oh.