EDIT After doing more testing, player:LoadCharacterWithHumanoidDescription(HumanoidDescription)
doesn’t seem to cause memory leaks, however this resets the character, thus resetting their position, and UI elements. So this isn’t a viable solution!
I’ve been having memory problems for the past days with my character editor. When you ApplyDescription() rapidly (50-100 times in a minute say) it starts to build up the LuaHeap in memory.
The hub says this
This is a yielding function. When called, it will pause the Lua thread that called the function until a result is ready to be returned, without interrupting other scripts.
Not sure if I’m understanding this wrong, but would this possibly be a cause?
Code looks like this
local function Update(player, category, item)
local Character = player.Character
if not Character then return end
local HumanoidDescription = Character.Humanoid:GetAppliedDescription()
UpdateHumanoidDescription(player, HumanoidDescription, category, item)
Character.Humanoid:ApplyDescription(HumanoidDescription)
HumanoidDescription = nil
end
UpdateCharacter.OnServerEvent:Connect(Update)
When I comment out the ApplyDescription it doesn’t cause these memory problems
local function Update(player, category, item)
local Character = player.Character
if not Character then return end
local HumanoidDescription = Character.Humanoid:GetAppliedDescription()
UpdateHumanoidDescription(player, HumanoidDescription, category, item)
--Character.Humanoid:ApplyDescription(HumanoidDescription)
HumanoidDescription = nil
end
UpdateCharacter.OnServerEvent:Connect(Update)
BUT I also noticed that commenting out my UpdateHumanoidDescription and keeping the ApplyDescription there also doesn’t cause memory problems
local function Update(player, category, item)
local Character = player.Character
if not Character then return end
local HumanoidDescription = Character.Humanoid:GetAppliedDescription()
--UpdateHumanoidDescription(player, HumanoidDescription, category, item)
Character.Humanoid:ApplyDescription(HumanoidDescription)
HumanoidDescription = nil
end
UpdateCharacter.OnServerEvent:Connect(Update)
So how can I debug this? I’ve tried to create a repro, but it won’t work. There has to be something about HumanoidDescriptions I’m missing. Is it how I’m editing the HumanoidDescription?
This occurs for all changes across the humanoiddescription (adding accessories, changing body color, face, clothing, etc.)
In case it’s necessary
local function UpdateHumanoidDescription(player, humanoidDescription, category, item)
local PlayerData = player:FindFirstChild('PlayerData')
if not PlayerData then return end
local function AccessoryToPlayerData(id, accessoryName)
local Item = id
local NewValue = Converter.Convertr(Item)
NewValue.Name = id
NewValue.Parent = PlayerData.Character[accessoryName]
end
-- Set the PlayerData values
if category then
-- Updating character
local Data = PlayerData.Character:FindFirstChild(category)
if not Data then return end
if Data:IsA('Folder') then
-- Accessory
if Data:FindFirstChild(item) then return end -- if they already have the item worn, return
--if #Data:GetChildren() >= 5 then return end -- no more than 5 items per category
-- EDIT Need to check for VIP, and see if item requires VIP
local NewItem = item
local NewValue = Converter.Convertr(NewItem)
NewValue.Name = item
NewValue.Parent = Data
else
-- Value
for i, v in pairs(CustomiseData[category]) do
-- EDIT Need to check for VIP, and see if item requires VIP
local ID -- Whether its the ID (for Shirts, Pants, Faces, etc. or Name for Body Colors
if category == 'Body Color' then
ID = v.Name
else
ID = i
end
if item == ID then
Data.Value = ID
if category == 'Bundle' then
local Details = AssetService:GetBundleDetailsAsync(ID)
end
end
end
end
else
-- Loading character
if PlayerData.Character['Roleplay Name'].Value == '' then
-- No previous data
PlayerData.Character['Roleplay Name'].Value = player.Name
PlayerData.Character.Face.Value = humanoidDescription.Face
PlayerData.Character.Shirt.Value = humanoidDescription.Shirt
PlayerData.Character.Pants.Value = humanoidDescription.Pants
-- Set default accessories
for _, id in ipairs(humanoidDescription.HatAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Hats')
end
end
for _, id in ipairs(humanoidDescription.HairAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Hairs')
end
end
for _, id in ipairs(humanoidDescription.FaceAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Face Accessories')
end
end
for _, id in ipairs(humanoidDescription.NeckAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Neck Accessories')
end
end
for _, id in ipairs(humanoidDescription.ShouldersAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Shoulders Accessories')
end
end
for _, id in ipairs(humanoidDescription.FrontAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Front Accessories')
end
end
for _, id in ipairs(humanoidDescription.BackAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Back Accessories')
end
end
for _, id in ipairs(humanoidDescription.WaistAccessory:split(',')) do
if id ~= '' then
AccessoryToPlayerData(id, 'Waist Accessories')
end
end
end
end
-- Set HumanoidDescriptions for accessories
local HatAccessories = {}
for _, v in pairs(PlayerData.Character.Hats:GetChildren()) do
table.insert(HatAccessories, v.Name)
end
humanoidDescription.HatAccessory = table.concat(HatAccessories, ', ')
local HairAccessories = {}
for _, v in pairs(PlayerData.Character.Hairs:GetChildren()) do
table.insert(HairAccessories, v.Name)
end
humanoidDescription.HairAccessory = table.concat(HairAccessories, ', ')
local FaceAccessories = {}
for _, v in pairs(PlayerData.Character['Face Accessories']:GetChildren()) do
table.insert(FaceAccessories, v.Name)
end
humanoidDescription.FaceAccessory = table.concat(FaceAccessories, ', ')
local NeckAccessories = {}
for _, v in pairs(PlayerData.Character['Neck Accessories']:GetChildren()) do
table.insert(NeckAccessories, v.Name)
end
humanoidDescription.NeckAccessory = table.concat(NeckAccessories, ', ')
local ShouldersAccessories = {}
for _, v in pairs(PlayerData.Character['Shoulders Accessories']:GetChildren()) do
table.insert(ShouldersAccessories, v.Name)
end
humanoidDescription.ShouldersAccessory = table.concat(ShouldersAccessories, ', ')
local FrontAccessories = {}
for _, v in pairs(PlayerData.Character['Front Accessories']:GetChildren()) do
table.insert(FrontAccessories, v.Name)
end
humanoidDescription.FrontAccessory = table.concat(FrontAccessories, ', ')
local BackAccessories = {}
for _, v in pairs(PlayerData.Character['Back Accessories']:GetChildren()) do
table.insert(BackAccessories, v.Name)
end
humanoidDescription.BackAccessory = table.concat(BackAccessories, ', ')
local WaistAccessories = {}
for _, v in pairs(PlayerData.Character['Waist Accessories']:GetChildren()) do
table.insert(WaistAccessories, v.Name)
end
humanoidDescription.WaistAccessory = table.concat(WaistAccessories, ', ')
-- Body sizes (need to base sizes on age)
local Size = AgeSizes[PlayerData.Character.Age.Value]
humanoidDescription.DepthScale = Size
humanoidDescription.HeadScale = Size
humanoidDescription.HeightScale = Size
humanoidDescription.WidthScale = Size
humanoidDescription.BodyTypeScale = 0
humanoidDescription.ProportionScale = 0
-- Face/Shirt/Pants
humanoidDescription.Face = PlayerData.Character.Face.Value
humanoidDescription.Shirt = PlayerData.Character.Shirt.Value
humanoidDescription.Pants = PlayerData.Character.Pants.Value
-- BodyColor
humanoidDescription.HeadColor = BrickColor.new(PlayerData.Character['Body Color'].Value).Color
humanoidDescription.LeftArmColor = BrickColor.new(PlayerData.Character['Body Color'].Value).Color
humanoidDescription.LeftLegColor = BrickColor.new(PlayerData.Character['Body Color'].Value).Color
humanoidDescription.RightArmColor = BrickColor.new(PlayerData.Character['Body Color'].Value).Color
humanoidDescription.RightLegColor = BrickColor.new(PlayerData.Character['Body Color'].Value).Color
humanoidDescription.TorsoColor = BrickColor.new(PlayerData.Character['Body Color'].Value).Color
return humanoidDescription
end