I am trying to make a skin system for the StarterCharacter in my game.
Sometimes when I am trying to test it, the module script thing returns as nil.
Module script:
local SkinModule = {}
local Skin1 = Instance.new("IntValue")
Skin1.Name = "Skin1"
Skin1.Parent = game.ReplicatedStorage
local Skin2 = Instance.new("IntValue")
Skin2.Name = "Skin2"
Skin2.Parent = game.ReplicatedStorage
local Skin3 = Instance.new("IntValue")
Skin3.Name = "Skin3"
Skin3.Parent = game.ReplicatedStorage
SkinModule.Skins = {
["Skin1"] = {
Skin1;
};
["Skin2"] = {
Skin2;
};
["Skin3"] = {
Skin3;
};
}
SkinModule.Raritites = {
["Skin1"] = 10;
["Skin2"] = 11;
["Skin3"] = 12;
}
SkinModule.ChooseRandomSkin = function()
local randomNumber = math.random(1,100)
local counter = 0
for rarity, weight in pairs(SkinModule.Raritites) do
counter += weight
if randomNumber <= counter then
local rarityTable = SkinModule.Skins[rarity]
local chosenSkin = rarityTable[math.random(1, #rarityTable)]
if chosenSkin == nil then
print("Choosing skin")
SkinModule.ChooseRandomSkin()
else
print("Success")
return chosenSkin
end
end
end
end
return SkinModule
Skin choosing script (I apologize if it looks really bad, this is the first time I have tried to do something like this):
game.Players.PlayerAdded:Connect(function()
local acc = game.ReplicatedStorage.RandomizedAccessory
acc.OnServerEvent:Connect(function(player)
local skinModule = require(script.Parent.Skins)
local skins = skinModule.ChooseRandomSkin()
if skins == nil then
print(skins)
skinModule.ChooseRandomSkin()
wait(3)
print(skins)
end
if skins == "Skin1" then
print(skins)
print("h")
local shirt = game.ReplicatedStorage.Shirt:Clone()
local pants = game.ReplicatedStorage.Pants:Clone()
local hat = game.ReplicatedStorage.Hat:Clone()
local face = game.ReplicatedStorage.Face:Clone()
shirt.Parent = player.Character
pants.Parent = player.Character
hat.Parent = player.Character:WaitForChild("Head")
face.Parent = player.Character:WaitForChild("Head")
hat.Handle.Position = player.Character:WaitForChild("Head").Position + Vector3.new(0,0.208,0)
elseif skins == "Skin2" then
print(skins)
local shirt = game.ReplicatedStorage.Shirt2:Clone()
local pants = game.ReplicatedStorage.Pants2:Clone()
local hat = game.ReplicatedStorage.Hat2:Clone()
local face = game.ReplicatedStorage.Face2:Clone()
face.Parent = player.Character:WaitForChild("Head")
shirt.Parent = player.Character
pants.Parent = player.Character
hat.Parent = player.Character:WaitForChild("Head")
hat.Handle.Position = player.Character:WaitForChild("Head").Position + Vector3.new(0,0.208,0)
elseif skins == "Skin3" then
print(skins)
local shirt = game.ReplicatedStorage.Shirt3:Clone()
local pants = game.ReplicatedStorage.Pants3:Clone()
local hat = game.ReplicatedStorage.Hat3:Clone()
local face = game.ReplicatedStorage.Face3:Clone()
face.Parent = player.Character:WaitForChild("Head")
shirt.Parent = player.Character
pants.Parent = player.Character
hat.Parent = player.Character:WaitForChild("Head")
hat.Handle.Position = player.Character:WaitForChild("Head").Position + Vector3.new(0,0.208,0)
end
end)
end)
In my case, what should I define it as?
local SkinModule = { ["Skin1"] = Instance.new("IntValue",game.ReplicatedStorage),
["Skin2"] = Instance.new("IntValue",game.ReplicatedStorage),
["Skin3"] = Instance.new("IntValue",game.ReplicatedStorage)
}
--Accessing these values =
local Skin1 = SkinModule["Skin1"]
Try this
1 Like
Did this work at all? Let me know!
Am I supposed to change the parts below too? Should I change this part to this:
SkinModule.Skins = {
Skin1;
Skin2;
Skin3;
}
Or should I change it to this:
SkinModule.Skins = {
["Skin1"] = {
Skin1;
};
["Skin2"] = {
Skin2;
};
["Skin3"] = {
Skin3;
};
}
SkinModule.Skins = {
["Skin1"] = {
SkinModule["Skin1"]},
["Skin2"] = {
SkinModule["Skin2"]},
["Skin3"] = {
SkinModule["Skin3"]}
}
1 Like
It’s not working, I don’t really know why.
The same error is ocurring. Sometimes it returns as nil and sometimes it doesnt.
What do I do now? Are you still there?
What is returning nil? the Module??
or the function inside the module?
Oh, the function is returning nil.
For the skin module I would do this
local Skin = {}
-- the key is the skin's name and the value is the rarity
local skins = {
Skin1 = 10,
Skin2 = 20,
Skin3 = 30
}
local mostCommonSkin = "Skin3"
function Skin.chooseRandomSkin()
local randomNumber = math.random(1,100)
local count = 0
for skinName, rarity in pairs(skins) do
count += rarity
if randomNumber <= count then
return skinName
end
end
return mostCommonSkin
end
return Skin
Then in the server script I would do this
local Skin = require(script.Parent.Skin)
game.Players.PlayerAdded:Connect(function()
local acc = game.ReplicatedStorage.RandomizedAccessory
acc.OnServerEvent:Connect(function(player)
local randomSkinName = Skin.chooseRandomSkin()
local skinFolder = game.ServerStorage.Skins[randomSkinName]
local shirt = skinFolder.Shirt:Clone()
local pants = skinFolder.Pants:Clone()
local hat = skinFolder.Hat:Clone()
local face = skinFolder.Face:Clone()
shirt.Parent = player.Character
pants.Parent = player.Character
hat.Parent = player.Character:WaitForChild("Head")
face.Parent = player.Character:WaitForChild("Head")
hat.Handle.Position = player.Character:WaitForChild("Head").Position + Vector3.new(0,0.208,0)
end)
end)
You would add folders in server storage that have the assets for one skin.
Doing it this way would save you time writing the extra if statements and the code should also run faster. Although the algorithm for the randomness may not be what you want exactly.
1 Like
I think it always returns as nil so it always returns the mostCommonSkin but other than that, it works.
Is there any way to prevent it from returning as nil? It’s the entire reason I made the topic.
The reason it’s returning nil is most likely because you return chosenSkin inside
if randomNumber <= counter then
If randomNumber is never less than the counter, then it will end up returning nil because the code goes outside of the for loop instead of calling the function again. Functions return nil on default in Luau.
The solution I gave returns the mostCommonSkin the most because there is a 40% chance it will choose any other skin with the current numbers in the table and the way the randomness was coded.
I think I see what you’re trying to say, but is there any other way to do it?
I think the most simple way to do is to add a return statement outside the for loop in the function.
SkinModule.ChooseRandomSkin = function()
local randomNumber = math.random(1,100)
local counter = 0
for rarity, weight in pairs(SkinModule.Raritites) do
counter += weight
if randomNumber <= counter then
local rarityTable = SkinModule.Skins[rarity]
local chosenSkin = rarityTable[math.random(1, #rarityTable)]
print("Success")
return chosenSkin
end
end
return defaultSkin
end
The nested if statement inside of if randomNumber <= counter was removed because I don’t think chosenSkin can be nil.
2 Likes