Getting a specific object by name from a list of tagged objects - CollectionService

I want to make a checkpoint system with collection service that saves to datastores where it is possible to have a map of checkpoints and just teleport to the ones you click on. Please dont help me with making the checkpoint map or using datastores, just keep in mind the system needs to have these features to be implementable and the system needs to be as simple as possible (you should be able to teleport to the checkpoint just by the name)

The issue is that when you get a list of tagged objects you get an array and not a dictionary.

I have obviously tried getting them by name the normal way. But other than that I cant think of a good way to do it. I could just loop through all of them but I think that would be rather slow when I have a lot of checkpoints. I could obviously lower the amount of checkpoints by only loading the ones in the area you are in but I want the system to be as simple as it can be.

1 Like

Could you be more specific about what you want to achieve? As in why do you want to get a specific object from a CollectionService array? It would be easier to focus on a specific issue in your system. If it’s to do with the click-to-teleport part, I don’t see why that requires getting a specific tagged object.

How many checkpoints do you have in total? Have you benchmarked your method?

I am trying to make a map where you can click on checkpoints just like the one in super mario odyssey. The reason why I want to use collectionservice is simply because I want to have a unified system for recognising the objects and I think collectionservice Is the cleanest way to do so. If I have points I have on the map I also have to know where to teleport the player which I need a position… and yes I could just save the position somewhere for quick acess but I really want the cleanest way. This is why I have decided to use names and get the position by name.

All I am looking for is getting a certain object by name from the array that gettagged() gives you. The problem Is that that gettagged gives you array and not a dictionary.
So I am trying to find a way to get a specific object from the array by name whitout looping through it or just a way to get a object from a list of tagged objects

Again, I do not want to loop through them. I am looking for the cleanest method, I always try to.

I honestly think the cleanest way would be to have an attribute of the checkpoint that gives the position. This would essentially be one step since it would just be an event triggered function for when the player clicks on the checkpoint marker.

1 Like

I had this idea too but now you gave me a better idea. What if each of them was looped through by the server at the start and just copied them somewhere for quick acess. That could work very well!

collectionService = game:GetService("CollectionService")
local tag = "myCoolTagName"
local checkpoints = {}

-- load all tagged instances into the checkpoints table
local instanceList = collectionService:GetTagged(tag)
for i, instance in ipairs(instanceList) do
    checkpoints[instance.Name] = instance
end

-- when a instance is tagged add to the checkpoints table
collectionService:GetInstanceAddedSignal(tag):Connect(function(instance)
    checkpoints[instance.Name] = instance
end)

-- when a instance was removed from the tag then remove from the checkpoints table
collectionService:GetInstanceRemovedSignal(tag):Connect(function(instance)
    checkpoints[instance.Name] = nil
end)

-- now to get a checkpoint you simply do
local checkpoint = checkpoints["Name"]
print(checkpoint.Name)
1 Like

when you copy them somewhere do you mean like a folder?

and how do you access them from the folder?

if your using FindFirstChild

FindFirstChild also loops here is how FindFirstChild works

local function FindFirstChild(instance, name)
    local children = instance:GetChildren()
    for i, child in ipairs(children) do
        if child.Name == name then
            return child
        end
    end
end

so using FindFirstChild is identical to doing

local function FindFirstTag(tag, name)
    local instances = collectionService:GetTagged(tag)
    for i, instance in ipairs(instances) do
        if instance.Name == name then
            return instance
        end
    end
end

Oh so it doesnt matter. I just somehow thought that findfirstchild has some magical way of getting the object.

Btw dont dictionary acesses loop through the whole dictionary? I mean you could generate a memory adress with the key but I do not know much about how variables work and how code is run on computer.

Nope there is no magic unfortunately

When you use dictionaries Lua has a hash function to find the value in the table it’s very quick

You can find how Lua does it here
https://www.lua.org/source/5.2/ltable.c.html

But it’s very quick you don’t need to worry about it

Thats what I thought roblox used for findfirstchild… Or at least something like this

when you access parts like this then it uses the hash function

-- this does the hash function 2 times once for the Folder and once for the Part
local part = workspace.Folder.Part

Is there a way of making this work with a string?

Maybe like this?
local part = workspace["Folder"]["Part"]

I havent tried it because I do not have my computer right now.

That’s the same as doing

workspace.Folder.Part

But yes you can do it that way and use variables at the string

So I could still copy them to a folder at the start, and access them using this method or just use the method you presented at the start, right?

local partName = "the name"
local part = workspace.Folder[partName]

So you can do this if you put them in a folder it’s almost the same as how I originally showed you above

The method above uses a table while this method you put them in a folder

Also in the method at the top I showed you how to do

collectionService:GetInstanceAddedSignal(tag):Connect(function(instance)

And

collectionService:GetInstanceRemovedSignal(tag):Connect(function(instance)

But if you know that the tags never change you don’t have to do that part