Since the addition of collection service, I and I’m sure many other developers have opted to use it because of how simple it makes creating and managing features in our games. Being able to recursively search for instances with a given tag.
Currently, we have the :GetTagged() API, however, this gets instances in the entire game.
GetChildrenWithTag() allows us to direct the search in a particular area in the game hierarchy and potentially decreasing the overhead and/or search time when needing to get a certain instance.
As an example, let’s say I have a sandbox game that players are able to build houses in. I want to make a feature that lets the player search for a certain type of object in the house.
Now because this is a sandbox game, there may be a bunch of other players with this same object in their house, so doing GetTagged() wouldn’t just return the objects owned by said player, rather it’ll get everyone’s objects.
Can’t you just add a check if the object is in the player’s house?
I most certainly can, but that’s not the point, I have all these extra objects that I have to loop through and check just to get to what I want. Whereas with GetChildrenWithTag will only get me the objects in the location I want.
I want to bring this back up again because there have been multiple instances over the course of the past month where I have needed this feature.
First instance
Our game has maps with invisible barriers so players cannot escape. As part of the gameplay we do raycasts that should not be stopped by these barriers, so we have code that builds an ignore-list for raycasts. Our barriers are tagged and ideally we want to just use CollectionService:GetTagged() to return all the barriers in the world. However, :GetTagged()also includes barriers from maps that are currently stored in the ServerStorage. So if we were to use that method, we would get an array of which ~95% of objects are irrelevant.
Second instance
Our game uses custom characters, so instead of spawning a character with Player:LoadCharacter() we manually set Player.Character and then add it to the Workspace. However, this way we lose the functionality to automatically spawn the player on a SpawnLocation. So what do we do? Well, we use CollectionService of course! We tag all our SpawnLocations so we can use CollectionService:GetTagged() to return a list of spawns. But here we run into the same problem as before… This also includes SpawnLocation objects that are currently stored in the ServerStorage!
The work-around for this problem would be to use CollectionService:GetInstanceAddedSignal() to determine when an object is added and to then check if it is a descendant of the right object. And although this works for the first two instances, it does not work for a third instance I ran into:
Third instance
As part of our gameplay, we spawn objects in our world that have a script in them to execute their logic. This code only starts running once they are parented to the workspace. These objects might have to look for other objects with specific tags. In this case using :GetInstanceAddedSignal() does not work, because there might already be objects in the workspace with the tag I am looking for! So Instead I must use CollectionService:GetTagged(). However, here I once again run into the issue from before: These objects run code on the server side, so this also returns objects stored in the ServerStorage.
I would quite like this. I was planning out some features for vehicles and it would nice to be able to tag objects in the vehicle, like headlights for example, without having to loop through every headlight in the game and use IsDescendantOf() to sort them into a separate table when it spawns.
This would be extremely useful, since I base a lot of my UI heavily around tags this would be super convenient to keep a track of each panel & it’s animations. I would love to see this added to CollectionService, a feature that’s already been wonderfully executed.
It’s been a while! I’ve yet again run into needing something like this and thought to post about it!
In this case, I am creating a system where a player will get different rooms/locations sent to their client as they move around the game, for example…
The player starts in the Lobby then they decide to enter the shop, the Lobby gets unloaded and the shop loads, now I need to teleport the player to a specific entrance spot.
To make this system be flexible I want to give the entrance spot a tag so the part itself does not need to be a particular name as sometimes the name is required for something else…
Currently, I am resorting to using GetChildren / GetDescendants and checking each object with HasTag for a particular tag.
This is a bit of a workaround and rather inefficient than being able to use a single API and get the result I’m looking for.
Good grief, is this true! I’ve been using GetTagged() assuming that it only gets tagged things in workspace, so this could have been causing me issues and bugs this whole time and not realized it…
What I think this should be is, not a GetChildrenWithTag, but a second optional argument for GetTagged perhaps being the parent object to detect under. Perhaps this is a bit of a weird method for that, but it seems easiest - You’d just go :GetTagged(String, workspace) if you only wanted things in workspace, for instance.
I am actually super deflated at the thought that I need to re-code large portions of my game to add tons of redundant checks to make sure the items I’m getting tagged aren’t literally in server storage lol
While this feature could be great and usefull, there is another way to get tagged instances that are only under a certain location.
CollectionService:GetInstanceAddedSignal("TagName"):Connect(function(Instance)
if Instance:IsDescendantOf(workspace) then
--code
end
end)
for _, Instance in pairs(CollectionService:GetTagged("TagName")) do
if Instance:IsDescendantOf(workspace) then
--code
end
end
I do like this. sure, we can do it fairly quickly manually, but considering in my usecases at least, I’m only ever getting things in workspace, the fact it gets things from storage as well makes me think it’d be nice to just have it as an option to filter through
I’m working on something called ReferenceBuilder, its a declarative event-driven way of creating CollectionService-based objects.
This would be nice for performance if I went around implementing a way of narrowing by ancestors. (right now you can only narrow by class through IsA).