How can I prevent the NPCs from having the same outfits?

This is my final post today, I promise :sweat_smile:

Anyways, I was testing my game after adding randomized NPC appearances. The problems is 2/3 of the 3 npcs ALWAYS have the same outfit every time. I don’t know what could be causing it.

I spawn the NPCs in 3 at a time and 2 always have the same outfit. Tested this about 30 times.
(I counted.)

Script for spawning them + generating their outfits:


function generateNPCApearance(npc)
	local stuff = game.ReplicatedStorage.Accessory
	
	local bodyColors = stuff.BodyColors:GetChildren()
	
	local hairs = stuff.Hair
	local pants_folder = stuff.Pants
	local shirts_folder = stuff.Shirts
	
	local genders = {"Male","Female"}
	local gender = genders[math.random(1,#genders)]
	
	local shirt = shirts_folder[gender]:GetChildren()[math.random(1,#shirts_folder[gender]:GetChildren())]:Clone()
	local pants = pants_folder[gender]:GetChildren()[math.random(1,#pants_folder[gender]:GetChildren())]:Clone()
	local bodyColor = bodyColors[math.random(1, #bodyColors)]:Clone()
	local hair = hairs[gender]:GetChildren()[math.random(1,#hairs[gender]:GetChildren())]:Clone()
	
	shirt.Parent = npc
	pants.Parent = npc
	bodyColor.Parent = npc
	hair.Parent = npc
end

function spawnNpc()
    npc = NPCsFolder.NPC:Clone()
    generateNPCApearance(npc)
    npc.Parent = workspace.Map.NPCs
end
Screenshots of the Issue:

The pants are also always the same, but it isn’t in the pic because of the desk.
image
image
image
image
All of these pictures were taken one after another. This issue happened 4 times in a row (I stopped at the last picture. There has to be something wrong with my script :confused:)

1 Like

Simply define a variable that stores already used objects, and you might want to create a function that returns true or false depending if the table contains an item. If the table owns the item, find a new one. If not, use that item and add it to the table.

I mean that could work but is there a reason as to why the two always have the same outfit? Could it be because I spawn them all at the exact same time, causing it to edit 2 NPCs appearances at once?

I think it probably could be that the same number was rolled again, but it’s not editing two NPCs at once because the :Clone() method creates a new copy of an object every time spawnNpc() was used.

So basically its insanely bad luck (30 times in a row :sweat_smile:)

Btw thats pretty slim odds for two npcs to roll the same thing over and over out of this many items:
image
Theres even more in the non opened folders.

May just be luck since I’m only counting around 3 shirts in the screenshots. But are you using spawn() or coroutine.resume() to call the function? if you aren’t it just yields until 1 npc is done then does the next and this may be causing the problem, if you make a new thread for each npc it does them separately and may fix them wearing the same clothes.

2 Likes

Im not using spawn because its deprecated and I am also not using coroutines. I would like to know how to implement coroutines into this though. spawnNpc() is not called in a coroutine and neither is generateNPCAppearance(). Which function should I wrap in a coroutine?

You can learn about coroutines in Programming in Lua and the Roblox Developer Wiki.

I know how to use coroutines and what they do, I am just unsure of which function to wrap in a coroutine.

Oh, you should try wrap each one then both and see if which works for you.

Im going to try this and see how it turns out:

local newThread = coroutine.wrap(function()
	generateNPCApearance(npc)
end)
		
newThread()
1 Like

Nope. The last 2 still have the same appearances :confused:

AHA! I have found the issue. I added a one second yield at the end and now they all have separate appearances. When I do them all at once, they have the same appearance. Is there a way to maybe still make them immediately appear? :thinking:

1 Like

that’s good. You can try to decrease to wait to just the lowest it can go which is 1/30th a second. You can also try wrapping spawnNpc in a coroutine instead of generate.

I will try wrapping spawnNpc() in a coroutine to see what that does.

I need them to all appear at once, as there is a chance an NPC sitting down could get destroyed while they are being added, causing an overflow of NPCs and that breaks the game entirely :confused:

aaaand coroutines don’t do anything :pensive:
Im honestly drawing a blank, I can’t figure it out.

Can I see how you’re spawning the npcs?

function spawnNpc()
    npc = NPCsFolder.NPC:Clone()
    generateNPCApearance(npc)
    npc.Parent = workspace.Map.NPCs
end

when you do npc = NPCsFolder.NPC:Clone() you’re not making it a local variable to only that function. Does it need to be global or can you change it to local? I think changing to local may fix the issue.

Well, this is the full code. I also have a random chance for spawning VIP NPCs but that isn’t very relevant to the appearance of normal NPCs so I cut it out. Here is the full function in my code:

function spawnNpc()
	local isVIP = math.random(1,chanceOfVIP)
	local npc = nil
	
	if isVIP == 1 then
		npc = NPCsFolder.VIP:Clone()
		npc.Parent = workspace.Map.NPCs
		
	else -- spawn normal NPC
		npc = NPCsFolder.NPC:Clone()
		
		generateNPCApearance(npc)
		
		npc.Parent = workspace.Map.NPCs
		
		wait(1)
	end
end

Also code for spawning them:

for i = 1,EmptySpotsAtDesk,1 do
	spawnNpc()
end

Here is my final idea if this doesn’t work then I think settling with wait() will have to be the way to go for now. Use coroutine create like below in the for loop. And function spawnNpc() should be made local. local function spawnNpc()

for i = 1,EmptySpotsAtDesk,1 do
	coroutine.resume(coroutine.create(spawnNpc)
end

Unfortunately it does not work :frowning:

Also wait() is too short, I noticed that anything less than around .2 is too fast. I’ll keep trying to think of a solution, thank you for helping me :slight_smile:

unfortunate. for debugging could you add a print(math.random(1,9)) or use one of the tables, to see if the math.randoms are returning the same values over and over for each npc or if they’re not running the correct amount of times.

I tried the math.random(1,9) AND THEY PRINT THE SAME NUMBER EVERTIME! THE LAST 2! ITS DRIVING ME NUTS!

I don’t understand how the function can be running for 2 NPCs…