The issue could be due to ‘Chr’ being nil or not having the expected structure.
You could try something like this:
local DataStore = game:GetService("DataStoreService"):GetDataStore("ClothingSaveReset")
function Load(Chr, Plr)
task.wait(2)
local good, info = pcall(function()
return(DataStore:GetAsync(Plr.UserId))
end)
print(Plr.Name, "DataStoreRetrivalInformation", good, info)
if Chr and info then
if Chr:FindFirstChild("Shirt") and info.Shirt then
Chr.Shirt.ShirtTemplate = info.Shirt
end
if Chr:FindFirstChild("Pants") and info.Pants then
Chr.Pants.PantsTemplate = info.Pants
end
if Chr:FindFirstChild("Head") and Chr.Head:FindFirstChild("face") and info.Face then
Chr.Head.face.Texture = info.Face
end
if Chr:FindFirstChild("Accesory") and Chr.Accesory:FindFirstChild("Handle") and Chr.Accesory.Handle:FindFirstChild("Mesh") and info.Accesory then
Chr.Accesory.Handle.Mesh.MeshId = info.Accesory
Chr.Accesory.Handle.Mesh.TextureId = info.TextureAccesory
end
end
end
local function LoadCharacter(Plr)
task.wait(5)
local Char = Plr.Character
Load(Char, Plr)
end
game.Players.PlayerAdded:Connect(function(plr)
LoadCharacter(plr)
plr.Changed:Connect(function()
task.wait(2)
LoadCharacter(plr)
end)
end)
This script checks if ‘Chr’ and ‘info’ are not nil, then checks if each property exists before trying to access it.
You should never need to wait an arbitrary amount of time (task.wait) before running code. If you do, you’re not writing defensive code. Don’t rely on timing.
CharacterAdded is the canonical way to check when a new character is set for the player. You should be using this instead of Changed.
You should not be performing DataStore operations every time the character spawns as you will very easily hit request limits. Start caching.
In preparation for deferred mode, you should be making a named function that you connect to handle all event fires as well as any existing instances.
With Immediate signals, the character subtree is not guaranteed when CharacterAdded fires (usually, more specifically, any appearance items). It is important to design around this - you should use CharacterAppearanceLoaded when writing code that customises a character’s appearance.
You might end up with a code sample that may look something like this:
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local ClothingStore = DataStoreService:GetDataStore("ClothingSaveReset")
local appearanceInfo = {}
local function onPlayerAdded(player)
local success, ret = pcall(function()
return ClothingStore:GetAsync(player.UserId)
end)
if success then
appearanceInfo[player.UserId] = ret
end
local function onCharacterAppearanceLoaded(character)
local info = appearanceInfo[player.UserId]
-- Write ShirtTemplate, PantsTemplate, etc.
end
player.CharacterAppearanceLoaded:Connect(onCharacterAppearanceLoaded)
if player.Character then
if not player:HasAppearanceLoaded() then
player.CharacterAppearanceLoaded:Wait()
end
onCharacterAppearanceLoaded(player.Character)
end
end
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
This is not a full code sample, it’s only meant to show what it might look like and point out some issues with the original code sample. It’s intentionally incomplete and doesn’t account for a vast majority of practice problems (e.g. player connections leak memory since the Player instance isn’t destroyed on leave, no cache cleaning, no DataStore saving, etc).