Local script running twice

  1. What do you want to achieve?
    I have some local scripts in startercharacterscripts or some gui related scripts in a screengui within’ startergui and I want it to run successfully even if I reset.

  2. What is the issue?
    So the local scripts that I have set up are working perfectly when I’m using them but when I reset, they run twice. An example would be that it prints hi once but when I reset and I use it, it prints hi twice.

  3. What solutions have you tried so far?
    I tried doing ResetOnDeath to true and false on the GUIs and that doesn’t affect anything, when I put the local scripts in starterplayerscripts, it actually stopped double printing but I want a solution without having to move all the localscripts to starterplayerscripts.
    I also checked the devforum and I couldn’t find anything that helped me.

Server script:

local proximityPrompt = script.Parent.ProximityPrompt

proximityPrompt.Triggered:Connect(function(player : Player)
	local character : Model = player.Character
	local humanoid : Humanoid = character:FindFirstChild("Humanoid")

	if humanoid.Health == 0 then return end
	
	local questType : string = script.Parent.Parent.Parent.Parent.Name
	local questName : string = script.Parent.Parent.Parent.Name
	
	local data = DataManager:GetData(player)

	if PlayerService:HasQuest(player, questName) then
		print("has quest")
	else
		for index, quest : string in pairs(QuestLibrary[questType][questName].RequiredQuests) do
			if data.CompletedQuests[questType][quest] == true then
				enableDialogue_Net:FireTo(player, questType, questName)
			else
				requirementsNotMet_Net:FireTo(player)
			end
		end

		if (next(QuestLibrary[questType][questName].RequiredQuests) == nil) then
			enableDialogue_Net:FireTo(player, questType, questName)
		end
	end
end)

Local script: (located in a gui with ResetOnDeath set to true in StarterGui)

enableDialogue_Net:Connect(function(questType : string, questName : string)
	print("hi")
	local count = 1
	
	local player : Player = game.Players.LocalPlayer
	local character : Model = player.Character
	local humanoid : Humanoid = character:FindFirstChild("Humanoid")
		
	local playerGui = player.PlayerGui
	local quest = playerGui:WaitForChild("Quest")

	local questUI = quest:WaitForChild("QuestUI")
	local main = questUI:WaitForChild("Main")
	local dialogue = main:WaitForChild("Dialogue")

	local acceptButton = main:WaitForChild("AcceptButton")
	local declineButton = main:WaitForChild("DeclineButton")
	
	EnableDialogue(dialogue, acceptButton, declineButton, questType, questName, questUI, main)	
	
	local acceptConnection : RBXScriptConnection
	local declineConnection : RBXScriptConnection
	
	humanoid.Died:Connect(function()
		acceptConnection:Disconnect()
		declineConnection:Disconnect()
		DisableDialogue(questUI, main)
	end)
	
	acceptConnection = acceptButton.MouseButton1Down:Connect(function()
		print("accepted")
		
		count += 1 
		
		if count <= #QuestLibrary[questType][questName].Dialogue then
			dialogue.Text = QuestLibrary[questType][questName].Dialogue[count]
			acceptButton.Text = QuestLibrary[questType][questName].AcceptAnswers[count]
			declineButton.Text = QuestLibrary[questType][questName].DeclineAnswers[count]
			print(count)
		else
			count = 1

			acceptConnection:Disconnect()
			declineConnection:Disconnect()

			setDataQuest_Net:Fire(questType, questName)
			changeObjectiveText_Net:Fire(questType, questName)
			receiveQuest_Net:Fire(questType, questName)
			DisableDialogue(questUI, main)
		end
				
	end)
		
	declineConnection = declineButton.MouseButton1Down:Connect(function()
		declineConnection:Disconnect()
		acceptConnection:Disconnect()
		
		count = 1
		
		DisableDialogue(questUI, main)
	end)		
end)

requirementsNotMet_Net:Connect(function()
	print("requirements not met")
end)
1 Like

Yeah. That seems to be the nature of the beast. Personally, I think it’s a bug. It runs once from StarterPlayer, then again when it’s copied to Player.StarterScripts. The only solution that I can think of for this is to see where it’s running from. Something like this:

-- 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

So if the script does not have a Player class as an ancestor, then the script exits. Place this on top of all scripts that needs to be under player. As for me, I usually just make my scripts reentrant so they don’t cause problems if they run twice.

2 Likes

i was trying to find a solution that doesnt involve me putting it in starterplayerscripts, i put it in starterplayerscripts and it seemed to work fine, however, could you explain in depth what it is you do that prevents problems?

Unfortunately there is no solution but moving them all to StarterPlayerScripts. StarterPlayScripts are programs meant to run based on the player joining the game.

StarterCharacterScripts are based in the players character itself, so it will always run again after a player spawns, where StarterPlayerScripts usually will only run when a player joins.

If you only want the script to run once, you can have it destroy itself after printing hi, but I doubt you’d want that.

You’re going to have to move them all to StarterPlayerScripts

Wrong. That doesn’t work. Even for me they run twice in StarterPlayerScripts. I can prove it.

This first picture is when it runs from the player.

This second one runs from StarterPlayer.

And that’s both in the same run. Same thing happens on a reset. The server is only sending the command once, but since the receiving event is connected on both copies of the script, they both run.

@Endryeos I think it’s a bug, but I’ve been dealing with it.

2 Likes

can you tell me how to deal with it?

In my previous reply, I provided code for you to place at the beginning of your scripts that must run from the player only. This will not work for module scripts though because they have to return a single value, so it will have to be modified for those. The alternative way is to write the script in such a way so it can run twice with no harmful effects, which is what I do. However, that method requires an advanced understanding of multitasking and multithreading to make the script reentrant.