How to get children of an instance in the same order on server and client

So, the title may not be clear. I will try to clear it up. I have, in this example, a folder called “stuff”, with 5 items in it.
image

Then, I have two script with the same code in them:

local stuff = workspace:WaitForChild("Stuff")

for i,v in pairs(stuff:GetChildren()) do
	print(i, v)
end

One of the scripts is in Workspace, the other is in StarterPlayerScripts.
This is what my output looks like:
image
My issue is not specifically the order of the items, that is irrelevant. My main issue is that the orders are different. The server has them ordered in the order I created them, and the client seems to have them randomly ordered. Is there any way of fixing this? Are there any function better than GetChildren()? If I can’t find anything, I’ll probably just run GetChildren() on the server and then pass it to the client. While I could create my own table in the script, I’d rather not do that because my dataset will be large, and I want it to be dynamic so that every time I add a new element to the folder, I won’t have to also update my table.

P.S: Preferably, the order of the table returned by GetChildren() or the equivalent better function will have the same output each time, it would be bizarre for the order of the items to change every time the game is loaded.

Thanks in advance!

2 Likes

Try this:

local stuff = workspace:WaitForChild("Stuff")
local number = 1

for i,v in pairs(stuff:GetChildren()) do
    if v.Name == number then
        number += 1
        print(v.Name)
    end
end

Simple:

for index, part in ipairs(#Stuffs:GetChildren())
        local p = Stuffs[index]

end

Yeah, Roblox recently-ish changed how loading in works. Instances no longer load in the order they were created. You can use the methods the others have given, or optionally if you want something more advanced, you can use table.sort.

Changes to Sibling Instance Ordering Sent at Game Load

Replication causes this. Things don’t implicitly exist on the client, they have to be given that content from the server during game initialisation. You will never get a properly ordered list and you shouldn’t expect an ordered list either. You’d have to sort after using GetChildren.

If your issue doesn’t lie in the way the items are ordered then you can handle this case on the client as your systems need it. I don’t think there’s a need to cross the client-server boundary to deliver references that already exist, but if ordering matters then that’s a special circumstance.

Fairly worth noting that the server is not guaranteed to return an ordered list either. GetChildren on the server returns items in the order they were put into the folder from Studio; your explorer automatically displays them in descending order (top lowest, bottom highest).

1 Like

This could work, but in my actual use case, the names are strings, not explicitly numbers.

This entirely crashes. ipairs is expecting table, but by using the hashtag it is receiving a number. Also, ipairs and pairs act the same when the table is an “array”, that is a table with ordered, numerical, indices. So this doesn’t work.

table.sort iterates through the table using comparative operators, which don’t work on Instances. I could create a second table of the Instance Names, but preferably I’d like a solution which is less complex/more efficient.

Is there any way you’d suggest for sorting the table? As I said above table.sort is not an option. Or, is it possible to pass the folder to the client after they join, as the post about the changes seems to say that objects replicated to the client after creation replicate in an ordered manner.

GetChildren is a table. table.sort has a second variable, which is the sort function. You’d put in your own sort function in order to work with whatever your table has.

If you’re just ordering by the numbers in the names, table.sort won’t be needed as you can directly reference the parts already with a simple for loop. But if you want more advanced sorting, such as comparing properties or attributes or some other thing, a sort function is what you’ll want.

If you wanted to use names with sort, even though you wouldn’t need to in this case, it would look something like this:

local sort = function(a,b)
	return a.Name < b.Name
end
local children = stuff:GetChildren()
table.sort(children,sort)
for _,v in pairs(children) do
	print(v.Name)
end
6 Likes

Thankyou, this is what I was looking for. I should have probably looked a little deeper, I didn’t even consider this, but it works great.

1 Like

I assumed you’re not clear enough of my idea.

It doesn’t mean that I can use either ipairs or pairs for any kinds of tables I encounter, but for the sake of better code readability. Also, my idea was to use the index value to find the instance correctly:

for index, _ in ipairs(Stuff:GetChildren()) do
    print(Stuff[index])
end