Is GUID really needed for unique ids?

Hi there,

So I thought about generating unique IDs, and how to accomplish this. IDs should be unique for every player in the game, and one player should have the possibility to generate almost endless amount of IDs.

I then read up on GUID a Roblox HTTP service
https://create.roblox.com/docs/reference/engine/classes/HttpService#GenerateGUID

After reading a few posts on the forums here, I came to the conclussion that this does not guarantee a unique number, but instead the chance of a repeating number is close to impossible.

But isn’t it more effecient to use a combination of Player.UserId and then each time that specific UserId generates a new ID, we just add +1 to the end number? (seperated by a underscore).

I would look something like this:

local UserId = 238224712
local GenerationId = .. -- This is a data we save in their datastore, that goes up by 1 each time they generate a new number
-- Generate IDs
local Ids = 3 -- Generates 3 Ids
local Generated = {}
for Count = 1, Ids do
	table.insert(Generated, UserId.."_"..GenerationId)
	GenerationId:Increment(1) -- This sample uses the DataStore2 datasaving module
end

for _, Id in pairs(Generated)
	print(Id) -- Prints generated Id
end

Output will look like the following:

--238224712_1
--238224712_2
--238224712_3

With this method we can generate a new unique id for each player, each second for 285616415 years, before hitting the ceiling of Ids.

Please let me know if and why GUID would be better for unique IDs.

I believe GUID is 100 percent unique. It is generated differently based on your mac address.

A true GUID is very difficult to create because to make sure its unique you have to do one of two things:

  • Check every already-issued GUID to make sure its not a repeat
  • Always use the next GUID in a non-repeating sequence

To narrow down what you actually need from this, think if its possible to reduce how “global” the uniqueness is. Is it okay for your ID to be unique withing all the ID’s given to that player? Or does it actually have to be unique among every GUID of that type issued?

It has to be unique for every single ever created unique ID in my game. With the method above, we use the UserId in combination to their previously generated IDs to accomplish this.

In that case, since the player id is unique, as along as the number after the underscore is also unique, then yes your system works and is globally unique. The number after the underscore actually only has to be unique within that player’s GUIDs, but you seem to know that.

Yea I was aware that it would be globally unique. What I really needed some feedback on, is if the HTTP GUID service is a better approach, and why. :slight_smile:

HTTP GUID is probably less suitable because it does not make the same assumption about starting with a unique player number and might have to work harder to give you a globally unique number.

UUID (from my understanding refers to the same thing as GUID) does not require a check for all previously issued IDs as stated here (UUID - Wikipedia).

I came across a few replies, that indicated that this is not the case with Roblox GUIDs, this is one of them. Is Roblox's UUID (GenerateGUID) system actually gaurenteed unique? - #8 by Ozzypig

Also your approach has slightly better intention, but you could generate the second number in a way similar to how HTTP does it, which is to say just generate a very large random number. Your way is guaranteed to be unique which is technically if slightly better than “almost absolutely certainly unique”.

This will have the same issue that GUID generation has, that it will leave behind a possibility of duplicates, the chance is way less since it’s for each player instead of the whole “GUID database”.

And the Ids that GUID generates also has a longer byte length.

UUID’s are not guaranteed to be unique either, but the risk of collision is so close to zero they are treated as completely unique. More on collisions may be read here: Universally unique identifier - Wikipedia.

For your use I think it would be better to simply do what you did, where you have userid_n where n goes from 0 → inf. This ensures it will be unique, as userids are unique. Incrementing means you will never have a collision either.

Video explaining how incredibly unlikely it is: Combinations of 52 cards (52 factorial) - YouTube. This is 52 factorial, which is aprox 10^67, while UUIDs are around 10^38 or something like that. There is a huge difference, but I think this will still provide a sense of scale.

The chance is unbelievably small, and it is made smaller by the fact you are limiting it to per player. For a 128 bit GUID (what HTTPService uses), you will on average have to generate 2^64 GUIDS before you get one duplicate. This is as unlikely as getting struck by lightning (1 / 15000) 1 quadrillion times in your lifetime.

Since you’re using a datastore to keep track of the next ID, make sure you think about what would happen if someone used a dupe technique to generate the same ID twice. Data stores on their own are susceptible to certain kinds of dupe tricks to read the same data when it should have been changed, theres a thread about how to avoid this on devforum community tutorials but I can’t find it anymore.

Thanks for the feedback. I’ll stick with my approach, since it seems like there is no superior advantage of using the HTTP service.

Since I do every sanity check on the server, I think that this wont be an issue.

That doesn’t guarantee that your read → increment → write to the datastore is atomic.

I found the post I was thinking of: Preventing duplication and data loss from trading

Well my sanity checks already prevents this issue, but thanks for clarifying. :slight_smile:

Thanks in advance! :slight_smile:

There are 2 ways to generate unique identifiers:

incrementing an identifier (like what you proposed)
randomly generating an identifier

Incrementing an identifier is easier, but it’s not always the best choice. It suffers from two problems:

It’s not very scalable. If you’re generating an identifier for a single person, it may be fine. But if you’re generating identifiers for many users, you have to have some way to keep track of the last used identifier. You can do this by storing the last used identifier in memory or in a database. But this means that you have to have a central server that can keep track of everything.
It’s not very secure. If you generate an identifier based on the user’s ID, someone can guess the next ID. This is a problem if the ID is used to do something like unlock some data.

Randomly generating identifiers is better. You can randomly generate identifiers on the client side instead of having to store stuff on a central server. Random identifiers are harder to guess, so they’re more secure.
There are two ways to randomly generate identifiers:

Use a function like GenerateGUID
Use a random number generator.

GenerateGUID has the drawback of not being reproducible. If you need to be able to reproduce the same identifier, you can’t use it. It’s also not very random.
The ideal solution is to use a cryptographically secure random number generator. This type of random number generator is designed for security and is guaranteed to generate numbers that are unpredictable and can’t be guessed.