After the replies to this topic, I feel the need to emphasise here this issue is with LocalScripts, NOT with Scripts with RunContext set to Client.
I have recently found an issue where any script put into StarterCharacterScripts is being run twice. This is a big issue for some systems in my game and others.
Here’s an example:
--LocalScript in StarterCharacterScripts
print("run")
--blah blah, other code
Reproduction steps:
Open a published Roblox place. This issue did not happen for me in a local place in Studio.
Insert a LocalScript into StarterCharacterScripts.
Put in this code:
local val = game:GetService("ReplicatedStorage"):WaitForChild("Value", 2) or Instance.new("BoolValue", game.ReplicatedStorage)
if val.Value then
print("Value is true, returning.")
return nil
end
val.Value = true
print("run")
Run in Studio or the Roblox engine, this bug occurs in both.
Observe how both print messages show in the output despite it only being one script that should only be run once.
This bug happens in Studio as well as in the Roblox engine.
System information:
CPU 11th Gen Intel(R) Core™ i5-1135G7 @ 2.40GHz 2.42 GHz
RAM 8GB
OS Windows 11 version 24H2
Version 64-bit
Expected behavior
LocalScripts in StarterCharacterScripts should only be run once.
I just tried to see what happens on my game, and it doesn’t run twice. Maybe you have plugins or another systems (/scripts) interfering. Consider that when the LocalScript is cloned or enabled (disabled) it’ll run again.
I have no plugins or other scripts interfering. It’s only one LocalScript with that line in it and no other scripts are enabling/disabling/cloning it. I also just tested it and both the outputs are coming from the same script.
It’s a really weird issue.
I also just tested a system with one of my LocalScripts where it clones a separate script to output a message from ReplicatedStorage but also uses a BoolValue to detect whether it’s been already run or not. I can confirm the LocalScript only gets cloned once, and then the message is outputted twice.
Just saw this code-example on this post, so try adding the code on the top of the script.
-- Check to see where the script is running from. If a player
-- is not an ancestor, then we exit.
local ancestor = script:FindFirstAncestorOfClass("Player")
if ancestor == nil then
return
end
If the script runs, then it’s first ancestor is of class “Player”, otherwise, it won’t run.
This is one of the reasons where if I have scripts I want to run with the Character, I just use regular StarterPlayerScripts and listen to the character event. It’s inconsistent as well
Are you 100% sure that the test you ran was on a LocalScript, not a Script with it’s RunContext set to Client?
You said you don’t have other scripts interfering; however, in that specific place, do you have any scripts that calls LoadCharacter even if your Players.CharacterAutoLoads is set to true in this specific scenario? If so, that is your problem. If not:
Have you tried running the same test on another place or on an empty, published place? If the issue is gone, it is a problem with your place and the way you are handling characters and/or their contents. If the issue still persists, not all plugin code appears on the Plugins window. Ensure you are running studio with no plugins.
I’ve only got one, half-complete plugin by me that doesn’t interfere with this kind of thing at all. I tried disabling it but the issue still persists. It sounds like other people have had the issue before, as well.
I took another look at the post @FederalTactical linked and compared it to mine, and I think I have the same issue… The scripts will run once under StarterCharacterScripts, and once in the workspace itself, under the player character. It only happens on places that have a lot of assets to be loaded when the player joins - I can’t reproduce it on a blank baseplate or smaller published place. This makes it inconsistent, which is very annoying.
I also can’t find a workaround :>
So I decided to report it because I couldn’t find someone who had already reported it
Can you run this code and screenshot what the studio output looks like in your problematic place. Curious to see what can be causing this.
--!strict
local prefix: string = `[{script.ClassName} {script:GetFullName()}]`
print(prefix, "Started running")
script.AncestryChanged:Connect(function(): ()
-- this shouldn't run since spawning gets destroyed,
-- but added just to see any unusual behavior
warn(prefix, "Ancestry changed")
end)
workspace:GetAttributeChangedSignal("foo"):Connect(function(): ()
-- this should only run once in a normal environment
print(prefix, "foo changed")
end)
workspace:SetAttribute("foo", true)
I also tried the printing run message again, and I got 2 responses. I thought one might be from a cloned character in a viewport frame that I made clone, but when I opened both messages and clicked “Show in Explorer”, they both pointed to the script under my character. So it’s not that one is run under StarterCharacterScripts and one is run under the character…
Here’s a few images (couldn’t take video):
so I select “Show in Explorer” on both messages and they both point to the same script.
The idea is the scripts run on the client, so the RunContext set to Legacy or Server is useless, and it happens for both Scripts with Client RunContext and LocalScripts.
But thanks, because that uncovered another important detail - this issue only happens on the client.
This isn’t a bug, but rather part of how RunContext works. RunContext is supposed to allow scripts to run anywhere, and not allowing it to run in StarterCharacterScripts brings back the legacy behavior where the script’s parent affects how it runs.
The last few posts have run off of the actual bug. As I’ve already said, this happens for LocalScripts and Scripts with a RunContext of Client. This shouldn’t happen. Setting it to Legacy or Server causes it to run on the server where it doesn’t happen.
LocalScript
Runs twice when placed in StarterCharacterScripts. Not expected behaviour.
Script with RunContext set to Enum.RunContext.Client
Same behaviour as LocalScript; runs twice when parented to StarterCharacterScripts. Expected behaviour for that script type.
Script with RunContext set to Enum.RunContext.Legacy or Enum.RunContext.Server
Script runs once, but on the server. Expected behaviour.
In short - no matter the script setup, client scripts run twice when parented to StarterCharacterScripts (though they run under the character). It does not happen when they are moved to the character after a set interval from another location, which provides a workaround, but this is still incredibly annoying.