Upcoming API change: Tools inherit Models

As a small piece of API cleanup, we’ll soon be changing the base class of BackpackItem from Instance to Model. Sounds scary but this effectively just means that Tools will start acting like Models:

  • Tools will remain Tools as they always have been, but…
  • tool:IsA("Model") will return true
  • They’ll have a Pivot / PrimaryPart (so PivotTo / MoveTo etc can be called on them)
  • The Roblox Studio draggers will start treating them exactly like any other Model
  • They’ll still have the same pick up / equip / drop etc behaviors you expect from them

We plan to release this change on January 31.

Motivation

  • Originally Tools were simple objects: Just containers with a single Handle part and a couple of scripts under them. Over time they’ve become more complicated, frequently containing many parts.

  • Over time Models have gained significant functionality such as pivots, and parts of the engine such as the package system and the Studio draggers have grown to depend on this extra functionality.

  • That means that Tools have been left as an awkward edge case, often requiring extra code in Studio tooling and other parts of the engine. The package system doesn’t even handle Tools gracefully: Tools that are packages count as modified if you drag them!

Changing the base class to Model eliminates all the odd edge case behaviors around Tools, having them take advantage of well-tested Model behaviors instead.

Backwards Compatibility

We don’t believe that there should be any backwards compatibility issues related to this change. To be extra safe, you can double check any cases in your code where you call :IsA("Model") in a context where Tools may be present, and make sure that nothing will go wrong when tool:IsA("Model") starts returning true.

Update re: FindFirstAncestorWhichIsA(“Model”)

Thanks for bringing up your concerns about existing code that uses this method to check for characters. We’ll do some analysis on this case and get back to you with our plans from there (work with devs to update that code, re-evaluate the change, or have some shim for that case, or some other options… there’s a lot of ways we could handle it).

Let us know if you have any concerns about the change.

204 Likes

This topic was automatically opened after 10 minutes.

To be honest this is a great change and makes way more sense for a tool to be a model rather then an instance. Small change and should not massively change a tool much but makes way more sense for it to be a model rather then being under as an instance.

21 Likes

Will IsA(“Tool”) continue to work?

13 Likes

Sorry, but if the class is being changed to Model, how do signal events such as Equipped work? Are they now an event of Model, or do they reside within models that have a Handle under them?

4 Likes

The way class inheritance works is not changing.


I’m a little sour that it took overhauling the appearance of the selection in Studio to finally incentivize making this change after a decade of complaining turned into stockholm syndrome, but happy to finally see it.

26 Likes

There’s a few features with tools that make this difficult to migrate over, mainly the Activation system which cleanly implements tool activation across the filtering bridge and also the difficult tool code. Please instead make it so Tool inherits Model instead of removing it.

7 Likes

Exactly the same. They are changing what it is under (rather then being classified as a instance it will now be classified as a model). It should still have all the normal events (such as .Equipped) and properties.

A normal instance does not have the event .Equipped as this is for tools only so I don’t see this changing at all due to it now being a model.

4 Likes

Rip every game that did raycast checks to see if it is a player by doing FindFirstAncestorWhichIsA(“Model”) you will not be forgotten.
On a side note, hey! Every single one of my games with raycasts is now broken :joy:

25 Likes

Please correct me if I am wrong but I don’t think the activation system for tools is being because it is an instance? If I am correct I don’t see how this would change in this because it is not changing from being a tool it is just changing from being an instance to a model.

4 Likes

no? if that was the case you would be able to do Player.Activated or game.Activated

5 Likes

This is a good point, is it possible for this to be enabled early in Studio?

4 Likes

cc @tnavarts This is actually a good point:

I just checked in one of my projects, our “explosive” item would break as a result of this:

Is there a better way to check if a given arbitrary model belongs to a player? Do we just have to loop through every player in the server & compare their character model to the current model?

14 Likes

Oh ok. I just though because if you check the docs for a tool the event .Activated shows up separately from the “Events inherited from Instance” which make me/made me believe it is not due to it being an instance (it inheriting it from being an instance).

Are you 100% sure it is from being an instance?


5 Likes

Will :Equipped still work?

2 Likes

Unsure if this fits your case, but for ClientCast, I verify whether the hit part is a character’s limb like so:

local ModelAncestor = RaycastResult.Instance:FindFirstAncestorOfClass("Model")
local Humanoid = ModelAncestor and ModelAncestor:FindFirstChildOfClass("Humanoid")
if Humanoid then
	ReplicationRemote:FireServer(Caster._UniqueId, "Humanoid", SerializeResult(RaycastResult))
end

Nevertheless, this is still a dangerous update as I’d imagine a lot games are going to suddenly break due to this seemingly unrelated change.

6 Likes

Yeah worst case, I can just create a boilerplate module called IsModelACharacter

2 Likes

Do you mean .Equipped?

Also to answer your question yes it should. .Equipped is due to being from the tool itself not being inhearted from an being an instance.

2 Likes

It is still an Instance, they are just adding another link in the inheritance. It use to go Tool > BackpackItem > Instance but now it’s Tool > BackpackItem > Model > (PVInstance) > Instance.

tl;dr; tools are still Tools, they are just also Models now.

The .Equipped event will still work. The class of tools isn’t changing, they are just making Tool a subclass of Model. All that does is add the model’s functions and properties to the Tool class (and make Instance.new("Tool"):IsA("Model") return true, just like how Instance.new("Part"):IsA("Instance") returns true)

2 Likes

I usually do something like this

for _,player in Players:GetPlayers() do
  local character = player.Character

  if not character  then
    return
  end

  if hitPart:IsDescendantOf(character) then
    return character
  end
end
1 Like