In my game, the player is given a basic face accessory. The player can then upgrade and equip new face accessories.
Problem:
When testing in studio and testing alone in the game, I can equip the face accessory without an issue. When I enter the game, I get the basic one and then go to the shop to equip a new one. But when there are multiple players, the face accessory vanishes after a few seconds. When I equip a new one, I can see it for a moment and then it disappears as well.
I’ve tried removing any face accessory from the players first (that they wear when entering the game) and then giving the new in-game accessory. I have also tried to just give the accessory. I’ve also removed the module being called when character is added or player appearance loaded (it’s just in PlayerAdded and the shop function now), but I always get the same result.
--// ServerScript
local function onPlayerAdded(Player)
-- different code here --
local character = Player.Character or Player.CharacterAdded:wait()
WeldStorage2.AttachToBack(Player, StorageFolder:GetChildren()[1])
end
game.ReplicatedStorage.Remotes.ShopDone.OnServerEvent:Connect(function(Player)
local PlayerDataFolder = PlayerData[Player.Name]
local ToolHolder = Player.HoldingFolder
if ToolHolder:GetChildren()[1] then
ToolHolder:GetChildren()[1].Parent = Player.Backpack
end
Player.Character.HumanoidRootPart.Anchored = false
WeldStorage2.AttachToBack(Player, PlayerDataFolder.ItemFolder.StorageFolder:GetChildren()[1])
end)
--//Module
local WeldStorage2 = {}
local OldObject = nil -- set previous storage to false for when player joins game
function WeldStorage2.AttachToBack(player, object)
if OldObject then OldObject:Destroy() end
local char = player.Character or player.CharacterAdded:wait()
local humanoid = char:WaitForChild("Humanoid")
local objectClone = object:Clone()
humanoid:AddAccessory(objectClone)
print(object.Name.." was added")
OldObject = objectClone
end
return WeldStorage2
This is expected because when a module is required after the first time it will return the same thing it did the first time. That being said, it means that OldObject will be shared among all players the method is called on. Simply change OldObject to a table where the key is the player and the value is the object.
Although this will cause another issue! We need to clear the index whenever the player leaves to avoid a memory leak. You can do this by adding a method to clear the index and removing it when the player leaves the game via PlayerRemoving.
Thank you for the quick response!
Could I create a function within the script then instead of calling a module? And would I have to remove existing face accessories first or would they be removed because the player can only have one at a time?
Like this:
–// ServerScript local OldObject = nil -- set previous storage to false for when player joins game
local function faceMask(player, object)
if OldObject then OldObject:Destroy() end
local char = player.Character or player.CharacterAdded:wait()
local humanoid = char:WaitForChild("Humanoid")
local objectClone = object:Clone()
humanoid:AddAccessory(objectClone)
print(object.Name.." was added")
OldObject = objectClone
end
faceMask(Player, PlayerDataFolder.ItemFolder.StorageFolder:GetChildren()[1])
The issue isn’t associated with the module. It doesn’t make much of a difference if it’s within the script or the module (it really just depends on if the functionality needs to be used in more than just that script). OldObject has to be a table in order to separate the face masks of each individual player.
Here’s how I would do it:
Code
local Players = game:GetService("Players")
local playerMasks = {}
function setMask(player, object)
if playerMasks[player] then
playerMasks[player]:Destroy()
playerMasks[player] = nil
end
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local clonedObj = object:Clone()
humanoid:AddAccessory(clonedObj)
playerMasks[player] = clonedObj
end
Players.PlayerRemoving:Connect(function(player)
if playerMasks[player] then
playerMasks[player] = nil
end
end)
Note: this pattern can be very repetitive so I’d suggest tracking it all in one place since you have to clear the indexes to prevent the memory from being leaked.