LET’S GOO!!!
This is SO much cleaner, idiomatic, in line with existing instance-level API that work with their own serialised data and feels so much better to write. It’s never made sense how collections were the only feature that didn’t have a discrete instance-level API but others had them (attributes started this way and CollisionGroups had their service-level sets deprecated to prefer writing CollisionGroup directly).
All of the improvements in this Release Note is a win
Glad to hear! Do note that because of unfortunate semantics with indexing, there are non-zero cases of people using instance names like GetTags and such for RemoteEvents, and their code not behaving the same anymore. This is going to happen regardless of if the flag is on or off, so I figured I would just mention it here.
This is so much better in many different ways!
I’m glad this feature is implemented, it’s great.
@Dogekidd2012 I want to provide a bit of feedback in regards to these features and services.
I like how ProximityPrompt has both its own API and a High level API, it is great for both macro and micro management. I think Attributes should have a high level API as well as any new Service/Feature that would make sense.
I want the ability to detect when an Attribute is added to an Instance for example. Moving forward would this be considered if it is possible to implement?
May I have your opinion too @colbert2677 ?
This sort of functionality for a wide array of services or instances would honestly be great. Dialog/DialogChoice instances and BadgeService (namely an awarded event listener) are the key ones that come to mind - essentially anything that has high surface area without custom wrappers or modules.
Why did you guys remove the ability to enable and disable shiftlock?
If you want my opinion: I’m all for features that make sense to have an micro/macro API. Tags having an instance-level API removes the absurd verbosity and addresses the weird issue of attributes being serialised onto an instance yet not having methods on itself to retrieve that.
It depends on the thing in question though. I don’t think a service-level API for attributes makes sense when you consider the design and intent of them (which is that they’re essentially developer-set properties more than anything). Macromanagement of attributes tends to be a very niche and specialised use case where you should probably build your own system for or review the way your system is designed and if that macromanagement is appropriate.
I do agree otherwise that a lot of other features should start this way.
-
Proximity prompts make sense because you may want to perform work on a specific prompt or on every single prompt (i.e. a certain condition may warrant a specific prompt being disabled, while another may warrant every prompt being disabled).
-
Tags make sense; the primary intent of tags are to form collections of instances. Those collections are internal and accessible through the service-level API when you want to macromanage a collection of instances. That being said, you should be able to read a single instance’s tags in case you want to keep that instance in the collection but only act on that specific instance in question.
-
Collision groups make sense because you want the service to determine collision group relationships but determine to specific instances which groups they should belong to.
-
Although SoundGroups are not service-level, the same idea still applies that you can use them to macromanage the volumes (unfortunately, not currently the PlaybackSpeed) of sounds, especially as they’re nestable. Assign a sound a SoundGroup, use the SoundGroup to apply something to a full group of sounds or customise the sound directly to only affect it.
-
Attributes wouldn’t make much sense; a comparative example is detecting changes against all the descendants of the DataModel. It’s performance heavy and there’s almost zero reason why you check all descendants. You want a system that only checks changes against the instances you pick. Similarly, treating attributes like properties, the same reason applies.
Attributes shouldn’t be used like tags, so your macromanagement is best handwritten for any specific use cases you might have. I understand the idea behind “check if any instance has X attribute added to it” or “find everything that has Y attribute” but those are best solved by combining attributes and tags together to best suit your needs.
Hope this opinion makes sense and is useful. I support macromanagement for a wide variety of use cases but attributes probably aren’t the ones you want an engine-built solution for.
After hearing a few days ago that both EnableMouseLockOption
and DevEnableMouseLock
would be deprecated with this release, I took a look at the API Reference to find out what would be superseding those properties, and I have a few questions and concerns I’d like to share.
MouseBehavior
When looking at either of the deprecated properties on the API Reference, it now recommends the following:
However, after going into Studio and running some tests, it’s unclear how it can be used with the :RegisterTouch/ComputerCameraMovementMode()
methods, as those appear to be exclusively used in PlayerScripts --> PlayerModule --> CameraModule LocalScript
for TouchCameraMovement
and ComputerCameraMovement
modes, which are completely separate from Shift Lock.
I tried the same format of PlayerScripts:RegisterComputerCameraMovementMode(EnumHere)
with the various MouseBehavior Enums and kept encountering the “Unable to cast token to token” error.
On top of that, the MouseBehavior Enums
page only mentions that it’s used for the UserInputService.MouseBehavior
property. Fortunately, this can be updated through scripts during runtime, so I was able to test those out and here’s what I’ve learned so far:
Impossible to force disable Shift Lock?
The three possible values for UserInputService.MouseBehavior
include:
Default: The mouse moves freely around the user’s screen.
LockCenter: The mouse is locked, and cannot move from, the center of the user’s screen.
LockCurrentPosition: The mouse is locked, and cannot move from, it’s current position on the user’s screen at the time of locking
For reference, the property is updated to LockCenter
when the player presses shift to lock the mouse. When unlocking the mouse, the property goes back to Default
. An example of when it’s updated to LockCurrentPosition
is when holding right click to adjust where you’re looking in third-person.
For developers that don’t want players to be able to use Shift Lock in their game at all, is it possible to completely disable the feature using the MouseBehavior
property (in a similar way to the simple and effective EnableMouseLockOption
bool) without needing to constantly listen for the property to be updated?
(Here’s what it looks like when EnableMouseLockOption
is set to false)
Furthermore, based on my testing, forcing the MouseBehavior
property to Default
whenever the property reads LockCenter
does not work as expected:
The example in the video used the following code:
local UserInputService = game:GetService("UserInputService")
UserInputService:GetPropertyChangedSignal("MouseBehavior"):Connect(function()
print(UserInputService.MouseBehavior)
if UserInputService.MouseBehavior == Enum.MouseBehavior.LockCenter then
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end)
-- I also tried this but that didn't change the results:
UserInputService:GetPropertyChangedSignal("MouseBehavior"):Connect(function()
print(UserInputService.MouseBehavior)
if UserInputService.MouseBehavior == Enum.MouseBehavior.LockCenter then
task.defer(function()
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end)
end
end)
Edit (May 24th, 2023): Even if this ends up being fixed, how can we be sure that the MouseBehavior
being set to LockCenter
was caused by the player entering Shift Lock mode and not zooming into the first person perspective? Adding additional checks to make sure we don’t accidentally set the MouseBehavior
to Default
while the player is in first person seems unnecessarily complicated in comparison to the existing solution of setting EnableMouseLockOption
to false from the get-go.
Limitations with MouseBehavior.LockCenter
It seems like there are three different scenarios where the MouseBehavior
is set to LockCenter
:
- When a player presses shift to lock the mouse.
- When a player goes into first-person mode.
- When a
LocalScript
updates the property toEnum.MouseBehavior.LockCenter
.
Although forcing the LockCenter
behavior does lock the player’s cursor to the center of the screen, it resembles what happens in first-person mode instead of the player-activated mouse lock, which is not desirable if a developer wants to enable the standard third-person shift lock (but would probably be fine for other use cases).
Here’s a quick example / comparison video:
The example in the video used the following code:
local UserInputService = game:GetService("UserInputService")
workspace.Part.Touched:Connect(function()
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
end)
-- Optional (for printing out the current value of the property in the Output)
UserInputService:GetPropertyChangedSignal("MouseBehavior"):Connect(function()
print(UserInputService.MouseBehavior)
end)
MouseBehavior.LockCurrentPosition does not retain locked position after opening and closing the escape menu
If MouseBehavior
is forced to be LockCurrentPosition
, the mouse cursor will be glued to wherever it was on the screen, as expected. When opening the escape menu, the mouse is unlocked (which makes sense so players can adjust settings, leave the game, etc.) but upon closing the escape menu, the cursor doesn’t return to its original locked position.
No idea if that’s intentional or not but I figured I would mention it anyway. Here’s an example video again for reference:
And here’s the code that was used in that example:
local UserInputService = game:GetService("UserInputService")
workspace.Part.Touched:Connect(function()
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
end)
Closing Thoughts
I do enjoy the extra control that is provided with the MouseBehavior
property, but currently, I’m disappointed with the following:
-
Unable to completely prevent players from enabling Shift Lock without scripts (not as seamless as setting
EnableMouseLockOption
to false.) -
Cannot enable standard third-person “Shift Lock” mode for players by updating
MouseBehavior
toLockCenter
. Only results in the first-person style of mouse lock.
In summary, it would be nice to have some clarification on the deprecation of EnableMouseLockOption
and DevEnableMouseLock
, as well as to have some insight into the functionality of the MouseBehavior
enums, property, etc.
Oh ok cool, Idk if you can tell me this or not but just wondering. Why was EnableMouseLockOption and DevEnableMouseLock deprecated in the first place?
Hi,
Thanks very much for the deep dive into it. We will take a take a look and get back to you soon.
Love the last two improvements! Thank you.
However, may I ask if Roblox could probably integrate functions like this to model? Or is calling functions like GetPartsInPart, part by part, the best option? Because I would love to do Model:GetTouchingParts() to know all the parts interacting with the model. Really useful for my building system which currently uses Model:GetBoundingBox() and then the function WorldRoot:GetPartsBoundInBox() to know the parts that are interacting with it. (Which is not accurate you know)
Unrelated:
Could we get a leak, if possible, about what is the property on OverlapParams named BruteForceAllSlow will be for? Will it be a way to make those functions yield and do tasks slower?
BruteForceAllSlow means “find all parts even if they have CanQuery = false”. You may for example, want to do this Studio plugins which would like to let the developer select parts regardless of their physical characteristics even if it has a non-negligible performance impact to do so.
The reason it’s slow is:
-
Setting CanQuery = false is telling the engine “APIs can’t query this”.
-
The engine, seeing this, doesn’t bother tracking the CanQuery = false part in its accelerated data structures in order to optimize performance.
-
You come barging back in saying “No, no… I really need to actually query those parts anyways” with BruteForceAllSlow.
-
The engine now has to no choice but to do things the hard way, manually looping through every single CanQuery = false part and testing it for intersection or raycast hits (where normally it can use the accelerated data structures to do things much more efficiently).
Similar performance reasons to above: The reason there aren’t functions like that on Model is that the engine doesn’t have any efficient way to do the test for a whole model, it would just be doing the same thing you would otherwise be doing looping over and testing the individual parts.
There is WorldRoot:ArePartsTouchingOthers
which can be used for optimization in some scenarios.
Thank you so much for the clear explanation, that new property will indeed be useful noting that I don’t disable CanQuery in many scenarios because else those API will ignore the part.
I will try using GetPartsInPart on every block then, now that it will be 2x faster as well. Thank you once again.
I have worked on a custom shiftlock script for mobile and I can say that MouseBehavior is NOT what we need for enabling/disabling shiftlock.
EnableMouseLockOption is on by default, so if you want to disable shiftlock, you need to set the property with the command line (which is stupid to have to do). There is no other good way to disable it (or recreate it yourself, if you want to keep a deprecated feature).
Why? Because all parts of shiftlock—the player automatically rotating due to camera rotation, the mouse being locked, and the camera being offset to the right—have no easy way to disable them. You could attempt to override the MouseBehavior and the UserGameSettings.RotationType, but these conflict with first person, which also sets these values. The CameraScript can get away with it as it knows if you are in first person or not, but there is no good way of checking for being in first person outside of it. Even then, you would still have the issue with the shifting to the right.
As for recreating shiftlock, similar issues occur. This time, there is no concern with conflicting priority with MouseBehavior or RotationType, but when shiftlock is disabled RotationType can pose a problem. MouseBehavior is always set back, but depending on the current version of the CameraScript (this behavior seems to change sometimes), RotationType may not get set back to MovementRelative, meaning you will continue to rotate even after disabling shiftlock. You could try to set RotationType to MovementRelative when shiftlock is disabled, but (also depending on the version) it may not be set back to CameraRelative if you were in first person when shiftlock was disabled. Finally, it is pretty easy to offset the camera a few studs to the right, but since there is no good way to detect if you are in first person, it will continue to offset in fist person, which doesn’t happen with vanilla shiftlock.
The deprecation of EnableMouseLockOption is ultimately negative for all developers, whether you want shiftlock enabled in your game or not. I sincerely hope the engineers consider reversing this deprecation, as it removes something that is impossible to recreate without bugs.
Hey, I was wondering if there is an estimate time frame for when Instance:HasTag(tag)
and the other Instance Tag methods becomes enabled? I am really looking forward to using this feature.
Behavior critical engine features which may be used on the client like that generally have to wait a few weeks for the next mobile force update after they ship, because until a mobile force update there’s still some clients out there in the wild without the feature.
you just gotta love the fact the Roblox staff ignore you when you ask genuine questions