I have made a task system where players and NPCs alike can go to a task center to pick up an task, such as “feed the cat” or “clean the kitchen”.
Later when the player or NPC arrives at the task location (cat’s food bowl or kitchen) they can “perform” the task for points.
In this system I need to uniquely identify the agent , either player or NPC.
What would be the best way of uniquely identifying the NPC/players?
If I was only caring about human players, I would probably use Player.UserId, but since there is no Player object for NPCs, what would be another good way to identify agents?
EDIT: To clarify, I don’t care if the agent in question is a player or an NPC. The whole point is that agents should be interchangeable. But I still need to know that agent X is agent X when she arrives at the task center, regardless of wether she is an NPC or human player.
Why don’t you use booleans in the player and NPC character models? When the player joins the game, you could add a bool value saying that they’re a player, and set it to false for NPCs.
The question is not to determine if an agent is a player or an NPC, the question is how can I tell agents apart, regardless of wether they are human players or NPCs.
Name them different things. You can give them all or some actual names like ‘John’ or simply name them based on something like ‘winterworldNPC1’ or just ‘NPC3’.
You could set up a folder under workspace for all NPCs, or, if you have level/world systems, you could set up a folder called ‘NPCs’ for that specific world/level.
Do something like game.Workspace.NPCsFolder.JohnTheTutorialNPC
I like this idea, but there is one problem, when testing in studio, many players will have the same name. Also, how can I guarantee that all the names I give are unique?
There were many good answers here, but in the end I solved this in a different way, and so I decided to share my result in case it could be useful to sameone else.
Basically I made a module script “AgentId” that is usable from both client and server (put it under ReplicatedStorage):
local module={}
local HttpService = game:GetService("HttpService")
function module.uuid()
return HttpService:GenerateGUID(false)
end
function module.getInstanceId(instance:Instance)
if not instance then
return
end
local id = instance:GetAttribute("uuid")
if not id then
id = module.uuid()
instance:SetAttribute("uuid", id)
end
return id
end
return module
At first glance this might seem a bit strange but please let me explain.
Attributes can be attached to any instance and are replicated. Whenever I ask for the ID of an NPC or player object with the getInstanceId() function it will return a UUID string that it generates on the fly if it is missing. This will automatically handle all sorts of problems which is kind of neat.
Things that it handles;
It supports ANY object, be it Parts, Models, Folders, Players, Characters, Humananoids or whatever else you need to identify.
It only stores ID when you need it, and so you don’t have to carefully manage when IDs are assigned. They are assigned at the first time they are needed.
It replicates automatically (given that ID is created on sever which is best practice anyways).
IDs are based on UUID which makes them globally unique, making chance of collision practically inexistent.
It uses Service to generate UUID which means it is probably fast (hopefully? I did not test this) .
Things that it does not handle;
IDs are not persisted in any way. Usually I find this is not necessary, and if it is, I can just use the same attribute and it will magically work with the rest.