We’ve just enabled a change that makes the Tool Instance type inherit from Model.
This means that:
tool:IsA("Model") returns true in scripts.
Tools now have a PrimaryPart and PivotTo / GetPivot can be called on them.
Tools which are packages can be moved without counting as modified.
Studio will treat Tools like Models eliminating various odd behaviors.
Won’t this break stuff?
This change will not have any impact on the vast majority of experiences. However, there is a specific usage pattern in some experiences which will be impacted:
Experiences which use part:FindFirstAncestorWhichIsA("Model") to find the character model associated with a part they’ve raycast into or touched will need to change this code. As Tools are now Models the code will now fail to find the character model for parts under a Tool being held by a character.
The solution is simple: Changing the code to part:FindFirstAncestorOfClass("Model") instead will resolve any issues related to this. We’ve used analytics to verify that gameplay in the small number of affected experiences isn’t significantly impacted either way but we would recommend updating your code if you were using that pattern.
Motivation
Tools started as simple Instances with a couple of scripts and a Handle part under them. Over the years they’ve grown to be much more complicated, typically containing a wide variety of scripts, modules, parts, visual effects, sounds, etc. Models have also gained a lot of capabilities in the last few years, and now support rich movement and positioning APIs.
Changing the base class of Tool to Model both brings Tools additional capabilities and allows us to remove some special case Tool handling code improving the consistency of Studio interactions.
Extra details
The pivot of Tools without a PrimaryPart set is treated as the pivot of the Handle part for better behavior with existing Tools.
The update hasn’t gone out to all mobile devices yet. You may still see some mobile devices where Tools aren’t models until the next mobile force update a week from now, so refrain from shipping code that use PivotTo on Tools just yet.
We’ve technically changed the base class of BackpackItem (the base class of Tool) to Model. This changes the inheritance of not just Tool but also HopperBin and Flag, however, those other classes are deprecated and unused in contemporary experiences so in practice only Tool is impacted.
This is a cool update, it’s nice to have tools be more intuitive to use. Will this change be added to accessories too? They are very difficult to position right now, as they don’t have access to PivotTo or similar features.
Yes, we considered this and will probably do it at some point.
However the doing it right now would have caused considerable breakage. Once this update gets people to migrate off of the FindFirstAncestorWhichIsA pattern most of the breakage potential will go away and we’ll come back to the accessory change. Though that’s not the only consideration, overall doing this for accessories will be a more involved change because of the complex interactions between accessories and characters.
I havent touched tools for quite a while now, but i am confused in which case you want to use PivotTo/GetPivot, could someone give me a small example/explanation?
If you have a bunch of things you want to spawn into the world some of which are Tools (E.g.: Spawning tools / pickups at the start of a round), previously you needed special code to handle placement of the Tools. Ideally you just make the same :PivotTo() call on all of that 3d content to position it, regardless of whether it’s individual parts, models, tools or whatever.
Same thing for being able to uniformly call :GetPivot() on something to find out where it is regardless of what type of object it is.
This is interesting. In the future, will we be able to set the handle’s weld to parts other than the right hand? Another request is the ability to choose the behavior of tool unequipping. My ideas are:
[Classic] (Current behavior.)
[StayEquipped] (Cannot unequip tools unless a script forces the unequip, or the tool is removed.)
[OverrideEquip] (Same as StayEquipped, but allows players to switch tools. This exists due to having to unequip one tool to equip another.)
If these could be implemented in the future, that would make tools much better.
Sorry to get your hopes up but unfortunately this change isn’t related to any larger arc of Tool improvements so don’t expect any other Tool changes in the short term.
Wouldn’t making a new instance be a great way to satisfy both parties? Older games can keep their functionality and newer games can take advantage to the new behavior.
Yes but that comes with a really high maintenance and ecosystem cost. Now both code we write internally and code developers write externally has to care about the fact that both exist.
The amount of breakage here was quite low which is why we were willing to just make the change. Only ~300 experiences with non-zero player count were impacted in any way and of those the core gameplay in most of them wasn’t affected, only some rare supplemental tool interaction. Furthermore we reached out to the few larger experiences and got them to update ahead of time to avoid any significant player impact.
Wouldn’t it be possible to only apply this behavior to games that have been opened after this update in studio?
This might break old games which don’t have active developers.
I didn’t read that only 300 games with players seem to be affected which seems very low.
But this approach could be used in the future, old games don’t care about new features.
I think it’s amazing that you’re able to detect potential breakage and reach out to individual developers ahead of time. In the future I hope this idea of breakage detection and direct contact is expanded upon so more drastic changes are easier to justify.
Are there any other unmentioned side effects of this recent update? My game’s tools no longer work due to the server not seeing children inside equipped tools anymore. I’ve posted further information about my issue here. This started occurring approximately near the same time that the update was announced.
Nice feature! I’ve always needed to transport all the parts of a tool to a specific location in the workspace and doing that was always a hassle. I had a condition set up a few days before it would take effect:
I do not think tool:IsA("Model") → true is a good idea. Alot of my games ultilize this, as getting characters from the tool. Not only this is not backwards compatible, It does not make sense generally.
Other than that, the extra functions in the tool that are like models is pretty good.
This also broke any code that expects Tools and Models to be mutually exclusive as they have been until this point. I’m not saying it’s bad to modernize things, but the :FindFirstAncestorWhichIsA("Model") use case certainly isn’t the only way something will have broken with this change.
if <thing>:IsA("Model") then
-- Do thing
elseif <thing>:IsA("Tool") then
-- Do other thing
end