NPC Passenger System - Math.random makes my script glitch so much I do not know what to say

I am making a trolleybus game, that uses completely randomized NPC passengers. Please read the whole post to understand the situation (a lot of small details)

How the system works:

  • There are multiple Spawn Pads at a bus stop, each having two scripts inside.
  • There is a folder in lighting, that has different body types, hair, faces, shirts and all that
  • One script in the Spawn Pad (“Spawn?”) randomizes if the NPC will even spawn - if yes, it enables the other script (“SpawnNPC”) to start randomizing the gender, body type, shirt, pants, hair, etc… (I will be naming all that as “clothing” from now on)

image
image

The problem that the scripts run into:

  • Multiple hair types, face types, shirt types, etc going into one NPC.

The outcome of the error:

  • Unused Hairs flying around cause they can not clip into the NPC.
  • NPCs looking extremely cursed with multiple clothing items on top of each other.

Details of the error:

  • Some NPCs do not have multiple clothing objects.
  • All NPCs only have at least one layer of randomized clothing. (as they should)
  • Using the print function, it seems that Spawn Pads, completely unrelated to the problematic NPC, are the ones to randomize the unneeded clothing when the NPC already has the clothing inside it.
  • Prints show, that Math.random does not choose multiple objects itself, but the “SpawnNPC” script just keeps getting triggered without a reason and then (for some reason) chooses items for a completely unrelated NPC.

I have tried absolutely everything (debounce, Removing math.randomseed, trying to understand where the problem came from with the print function, etc) and have not found a solution yet.

Codes in the Spawn Pad:

“Spawn?”

db = false

while true do
	if script.Parent.NPC.Value == nil and script.Parent.Parent.Parent.NPCs.Boarding.Value == false and db == false then
		db = true
		local g = math.random(1, 2)
		if g = 1 then
			script.Parent.SpawnNPC.Enabled = true
			wait(60)
			db = false
		end
		db = false
	end
	db = false
	wait(60)
end

“SpawnNPC”

math.randomseed(os.time())

wait(1)
local gender = "Man"
local w = game.Lighting.Wardrobe

--- GENDER ---
local g = math.random(1, 2)

if g == 1 then
	gender = "Man"
	print("õäõ Mathed Random - Man -" .. script.Parent.Name)
elseif g == 2 then
	gender = "Woman"
	print("õäõ Mathed Random - Woman -" .. script.Parent.Name)
end

--- BODY TYPE ---
local items = w[gender].BodyTypes:GetChildren()
local NPC = items[math.random(1, #items)]

print("õäõ Mathed Random - Body -" .. script.Parent.Name)

local NPC2 = NPC:clone()
wait(0.1)
NPC2.Parent = w[gender].BodyTypes
wait(0.1)

script.Parent.NPC.Value = NPC
NPC.Name = "NPC"
NPC.Manager.Enabled = true
NPC.HumanoidRootPart.CFrame = script.Parent.CFrame + Vector3.new(0, 3, 0)

print("õäõ Cloned Body -" .. script.Parent.Name)

--- LOOKS ---
local items = w[gender].Looks.Faces:GetChildren()
local face = items[math.random(1, #items)]
local face2 = face:clone()
wait(0.1)
face2.Parent = w[gender].Looks.Faces
wait(0.1)
face.Parent = NPC.Head
print("õäõ Mathed Random - Face -" .. script.Parent.Name .. face.Texture)

local items = w[gender].Looks.Shirts:GetChildren()
local shirt = items[math.random(1, #items)]
local shirt2 = shirt:clone()
shirt2.Parent = w[gender].Looks.Shirts
shirt.Parent = NPC
print("õäõ Mathed Random - Shirt -" .. script.Parent.Name)

local items = w[gender].Looks.Pants:GetChildren()
local pants = items[math.random(1, #items)]
local pants2 = pants:clone()
pants2.Parent = w[gender].Looks.Pants
pants.Parent = NPC
print("õäõ Mathed Random - Pants -" .. script.Parent.Name)

local items = w[gender].Looks.Hair:GetChildren()
local hair = items[math.random(1, #items)]
local hair2 = hair:clone() 
hair2.Parent = w[gender].Looks.Hair
hair.Parent = NPC
print("õäõ Mathed Random - Hair -" .. script.Parent.Name .. hair.Name)

hair.Handle.Position = NPC.Head.HairAttachment.Position

NPC.Parent = script.Parent.Parent.Parent.NPCs


--- SKIN COLOR ---
local skincolor = Color3.new(1, 1, 1)

local s = math.random(1,7)
if s == 1 then
	skincolor = Color3.new(1, 0.666667, 0.498039)
elseif s == 2 then
	skincolor = Color3.new(1, 0.764706, 0.572549)
elseif s == 3 then
	skincolor = Color3.new(0.811765, 0.541176, 0.403922)
elseif s == 4 then
	skincolor = Color3.new(0.647059, 0.431373, 0.321569)
elseif s == 5 then
	skincolor = Color3.new(0.862745, 0.627451, 0.431373)
elseif s == 6 then
	skincolor = Color3.new(0.709804, 0.529412, 0.309804)
elseif s == 7 then
	skincolor = Color3.new(1, 0.760784, 0.592157)
end

local descendants = NPC:GetDescendants()

for _, descendant in pairs(descendants) do
	if descendant:IsA("BasePart") or descendant:IsA("MeshPart") then
		descendant.Color = skincolor
		print("õäõ Mathed Random - SkinColor -" .. script.Parent.Name)
	end
end

NPC.HumanoidRootPart.CFrame = script.Parent.CFrame + Vector3.new(0, 3, 0)
wait(0.3)
NPC.HumanoidRootPart.Anchored = true
script.Enabled = false

just fire a RemoteEvent rather than enabling the script

2 Likes

Good suggestion, but something is still broken. Since these are server scripts I used BindableEvent. Now there are fewer problematic NPCs, but some still keep spawning with multiple clothing items. Could be just a coincidence.

Before using BindableEvent event:

After using BindableEvent event:

Here is what I did:
image

Spawn:

db = false

while true do
	if script.Parent.NPC.Value == nil and script.Parent.Parent.Parent.NPCs.Boarding.Value == false and db == false then
		db = true
		local g = math.random(0, 1)
		if g == 1 then
			local spawnpad = script.Parent
			print("NPC fired")
			script.Parent.SpawnNPC:Fire(spawnpad)
			wait(60)
			db = false
		end
		db = false
	end
	db = false
	wait(60)
end

SpawnNPCScript:

math.randomseed(os.time())

script.Parent.SpawnNPC.Event:Connect(function(spawnpad)
	print("NPC recieved")
	if spawnpad == script.Parent then
		local gender = "Man"
		local w = game.Lighting.Wardrobe

		--- GENDER ---
		local g = math.random(1, 2)
		wait(0.1)
		if g == 1 then
			gender = "Man"
			print("õäõ Mathed Random - Man -" .. spawnpad.Name)
		elseif g == 2 then
			gender = "Woman"
			print("õäõ Mathed Random - Woman -" .. spawnpad.Name)
		end

		--- BODY TYPE ---
		wait(0.1)
		local items = w[gender].BodyTypes:GetChildren()
		local NPC = items[math.random(1, #items)]

		print("õäõ Mathed Random - Body -" .. spawnpad.Name)

		local NPC2 = NPC:clone()
		NPC2.Parent = w[gender].BodyTypes

		spawnpad.NPC.Value = NPC
		NPC.Name = "NPC"
		NPC.Manager.Enabled = true
		NPC.HumanoidRootPart.CFrame = spawnpad.CFrame + Vector3.new(0, 3, 0)

		print("õäõ Cloned Body -" .. spawnpad.Name)

		--- LOOKS ---
wait(0.1)
		local items = w[gender].Looks.Faces:GetChildren()
		local face = items[math.random(1, #items)]
		local face2 = face:clone()
		face2.Parent = w[gender].Looks.Faces
		face.Parent = NPC.Head
		print("õäõ Mathed Random - Face -" .. spawnpad.Name .. face.Texture)
		wait(0.1)
		local items = w[gender].Looks.Shirts:GetChildren()
		local shirt = items[math.random(1, #items)]
		local shirt2 = shirt:clone()
		shirt2.Parent = w[gender].Looks.Shirts
		shirt.Parent = NPC
	print("õäõ Mathed Random - Shirt -" .. spawnpad.Name)
		wait(0.1)	
		local items = w[gender].Looks.Pants:GetChildren()
		local pants = items[math.random(1, #items)]
		local pants2 = pants:clone()
		pants2.Parent = w[gender].Looks.Pants
		pants.Parent = NPC
		print("õäõ Mathed Random - Pants -" .. spawnpad.Name)
		wait(0.1)
		local items = w[gender].Looks.Hair:GetChildren()
		local hair = items[math.random(1, #items)]
		local hair2 = hair:clone() 
		hair2.Parent = w[gender].Looks.Hair
		hair.Parent = NPC
		print("õäõ Mathed Random - Hair -" .. spawnpad.Name .. hair.Name)

		hair.Handle.Position = NPC.Head.HairAttachment.Position

		NPC.Parent = spawnpad.Parent.Parent.NPCs


		--- SKIN COLOR ---
		local skincolor = Color3.new(1, 1, 1)
		local s = math.random(1,7)
		if s == 1 then
			skincolor = Color3.new(1, 0.666667, 0.498039)
		elseif s == 2 then
			skincolor = Color3.new(1, 0.764706, 0.572549)
		elseif s == 3 then
			skincolor = Color3.new(0.811765, 0.541176, 0.403922)
		elseif s == 4 then
			skincolor = Color3.new(0.647059, 0.431373, 0.321569)
		elseif s == 5 then
			skincolor = Color3.new(0.862745, 0.627451, 0.431373)
		elseif s == 6 then
			skincolor = Color3.new(0.709804, 0.529412, 0.309804)
		elseif s == 7 then
			skincolor = Color3.new(1, 0.760784, 0.592157)
		end

		local descendants = NPC:GetDescendants()

		for _, descendant in pairs(descendants) do
			if descendant:IsA("BasePart") or descendant:IsA("MeshPart") then
				descendant.Color = skincolor
				print("õäõ Mathed Random - SkinColor -" .. spawnpad.Name)
			end
		end
wait(0.3)
		NPC.HumanoidRootPart.CFrame = spawnpad.CFrame + Vector3.new(0, 3, 0)
		wait(0.3)
		NPC.HumanoidRootPart.Anchored = true
	end
end)

I tried another way too - SpawnNPC as a script in ServerScriptService. Nothing changed and the problem was still there.

instead of this

local items = w[gender].Looks.Faces:GetChildren()
local face = items[math.random(1, #items)]
local face2 = face:clone()
face2.Parent = w[gender].Looks.Faces
face.Parent = NPC.Head
print("õäõ Mathed Random - Face -" .. spawnpad.Name .. face.Texture)

try something like this

local items = w[gender].Looks.Faces:GetChildren()
local face = items[math.random(1, #items)]:Clone()
face.Parent = NPC.Head
print("õäõ Mathed Random - Face -" .. spawnpad.Name .. face.Texture)

also, please use task.wait() and I would recommend using Clone() instead of clone()

and make sure to do this with shirt, pants, hair, etc not just the face

1 Like

Seems like task.wait was the solution. Didn’t know a thing like that existed. Thank you very much!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.