When a player’s character spawns, or LoadCharacter() is invoked, the CharacterAdded event is being fired twice for some reason.
At first, I thought maybe it was my code doing something, so I decided to isolate everything and test with this simple code:
LocalScript in StarterPlayerScripts
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local function _HandleCharacterAdded(character: Model): ()
print("Character Added")
end
player.CharacterAdded:Connect(_HandleCharacterAdded)
And the results are…
The function was invoked two times, leading to two prints, meaning the event got fired twice.
I tried everything to fix this, checking other forum posts on this topic, and reading Roblox Docs, but unable to find a solution.
Is this just a blatant engine bug? Is there a bandaid fix for this? How can I make it not fire twice, or at least catch the second firing attempt and just void it?
Hello. I inserted your script into studio and it only fired once for me.
Maybe try using find all/replace all tool and check if you didnt put same script somewhere else
You mentioned you call LoadCharacter(), is players.CharacterAutoLoads = false?
If setting this property via script, you will need to make sure it is done very early before any players get chance to have their character loaded automatically. (In studio this can be pretty quick).
If it is set to true, then chances are the load character call is simply reloading the character.
Can you put this code in for your print statement and let me know what outputs?
local function _HandleCharacterAdded(character: Model): ()
print("Character added. Script:", script:GetFullName())
end
Also:
It’s a LocalScript, not Script with RunContext set to Client, right?
Does this only happen in your place?
There’s no behaviour that could be causing the script to run twice? No rapid disabling or enabling it? No re-parenting?
Does this happen in Roblox as well as Studio?
As a workaround, you can debounce the function:
local db = false
local function _HandleCharacterAdded(character: Model): ()
if (db) then return nil end
db = true
print("Character added!")
task.wait(0.5)
db = false
end
I encountered a very inconsistent issue like this in the past and made a bug report on it, but I’m yet to find a solid repro for it.
A LocalScript in StarterPlayerScripts works fine and the event is fired once in my place.
What I haven’t said in my post, I probably should’ve, I am using module loader or Single-Script Architecture in my place. I connect to the CharacterAdded event in the module script when the module loads (the module is being required for the first time)
I apologize for any confusion and for not saying this before, as well as possibly misleading.
I tried out with new module script, I usually structure my modules like this:
Code
-------------------------------
-- == SERVICES & REQUIRES == --
-------------------------------
local Players = game:GetService("Players")
-------------------------------
-- == CONSTANTS & TYPES == --
-------------------------------
-------------------------------
-- == VARIABLES == --
-------------------------------
local Test = {}
local player = Players.LocalPlayer
-------------------------------
-- == PRIVATE FUNCTIONS == --
-------------------------------
local function _HandleCharacterAdded(character: Model): ()
print("Character Added")
end
-------------------------------
-- == PUBLIC FUNCTIONS == --
-------------------------------
-------------------------------
-- == HANDLERS == --
-------------------------------
player.CharacterAdded:Connect(_HandleCharacterAdded)
-------------------------------
-- == MAIN == --
-------------------------------
return Test
--!nonstrict
debug.setmemorycategory("ARC Framework - StaminaHandler")
-------------------------------
-- == SERVICES & REQUIRES == --
-------------------------------
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Signal = require(ReplicatedStorage.Modules.Utilities.Signal)
local StaminaClass = require(script.StaminaClass)
-------------------------------
-- == CONSTANTS & TYPES == --
-------------------------------
-------------------------------
-- == VARIABLES == --
-------------------------------
local StaminaHandler = {}
local staminaMap: { [Humanoid]: StaminaClass.Stamina } = {}
local player = Players.LocalPlayer
StaminaHandler.StaminaCreated = Signal.new()
-------------------------------
-- == PRIVATE FUNCTIONS == --
-------------------------------
local function _HandleCharacterAdded(character: Model): ()
local humanoid = character:FindFirstChildOfClass("Humanoid")
local stamina = StaminaClass.new(humanoid)
staminaMap[humanoid] = stamina
StaminaHandler.StaminaCreated:Fire(stamina)
end
local function _HandleCharacterRemoving(character: Model): ()
local humanoid = character:FindFirstChildOfClass("Humanoid")
staminaMap[humanoid]:Destroy()
staminaMap[humanoid] = nil
end
-------------------------------
-- == PUBLIC FUNCTIONS == --
-------------------------------
function StaminaHandler:GetStamina(humanoid: Humanoid): StaminaClass.Stamina?
return staminaMap[humanoid]
end
-------------------------------
-- == HANDLERS == --
-------------------------------
player.CharacterAdded:Connect(_HandleCharacterAdded)
player.CharacterRemoving:Connect(_HandleCharacterRemoving)
-------------------------------
-- == MAIN == --
-------------------------------
return StaminaHandler
For context, it is supposed to be a player stamina handler. It checks if the player’s character is added and creates a stamina class for that player’s character humanoid.
So I found out it was doing that because I had my StaminaHandler module nested in folders.
Un-nesting the module script, fixes the issue, but, I also tried with fresh module scripts and in nested folders they would work fine, CharacterAdded is caught once, not twice.
So it seems like my StaminaHandler module is being funky and does not want to sit in nested folders, because then it will catch the CharacterAdded event twice. Strange… Maybe it is because of some modules that I require and use? There’s a lot to figure out.