What is this dialogue script's problem?

Hello Developers!

Does anyone know what is wrong with this script? What happens so far is only the text gets to “Hello” but you can’t make it say the text after. Also, “Hello” is a bit delayed.

(Just find where I set ‘TalkText’ because that is the only bit that isn’t working

Any ideas?

local Distance = 10
local talking = false
local players = game:GetService("Players")
local player = players.LocalPlayer
local startergui = game:GetService("StarterGui")
local screengui = startergui.ScreenGui
local frame = screengui.Frame
local nf = frame.NextFrame
local nb = nf.NextButton
nf.Visible = false
nb.Visible = false
frame.Position = UDim2.new(0, 0,1.2, 0)
local talkable = true
local touching = false
while wait()do 
	for i,v in pairs(workspace:GetChildren()) do 
		if game.Players:FindFirstChild(v.Name) then 
			if(v.PrimaryPart.Position - script.Parent.Position).magnitude <= Distance then 
				if talking == false then
					touching = true
					local character = v
					local player = players:GetPlayerFromCharacter(character)
					local playerGui = player:WaitForChild("PlayerGui")
					local screenGui = playerGui:WaitForChild("ScreenGui")
					local frame = screenGui:WaitForChild("Frame")
					local tb = frame:WaitForChild("TalkButton")
					frame:TweenPosition(UDim2.new(0, 0,0.73, 0), "Out", "Back")
					local nextframe = frame:WaitForChild("NextFrame")
					local nextbutton = nextframe:WaitForChild("NextButton")
					if talkable == true then
						if touching == true then
							tb.MouseButton1Click:Connect(function()
								local talktext = frame:FindFirstChild("TalkText")
								talktext.Text = ""
								nextbutton.Visible = true
								nextframe.Visible = true
								tb.Visible = false
								talktext.Visible = true
								wait(0.5)
								talktext.Text = "Hello!"
								nb.MouseButton1Click:Connect(function()
									talktext.Text = "I'm Colour. The one and only!"
									nb.MouseButton1Click:Connect(function()
										talktext.Text = "And your name is..."
										nb.MouseButton1Click:Connect(function()
											talktext.Text = v.Name .. "?"
											nb.MouseButton1Click:Connect(function()
												talktext.Text = "Am I pronouncing that right?"
											end)
										end)
									end)
								end)
							end)
						end
					end
				end
			else 
				if talking == false then
					touching = false
					local character = v
					local player = players:GetPlayerFromCharacter(character)
					local playerGui = player:WaitForChild("PlayerGui")
					local screenGui = playerGui:WaitForChild("ScreenGui")
					local frame = screenGui:WaitForChild("Frame")
					local tb = frame:WaitForChild("TalkButton")
					local nextframe = frame:WaitForChild("NextFrame")
					local nextbutton = nextframe:WaitForChild("NextButton")
					local talktext = frame:FindFirstChild("TalkText")
					talktext.Text = ""
					frame:TweenPosition(UDim2.new(0, 0,1.2, 0), "Out", "Back")
				end
			end 
		end 
	end 
end

Yeah… pretty much the whole thing is wrong.

  • Above all, we have no idea if this is running on the server or client. Please provide more context than just your code so we can better understand your environment.

  • StarterGui isn’t what players see. In Studio it’s used as a place to develop your interfaces but when play (testing) everything in it is copied to a player’s PlayerGui. What players actually see and interact with is their PlayerGui.

  • While wait is bad code. It gets worse because you’re looping through all the children of the Workspace and that’s to find players. Instead of doing that, use GetPlayers so you will guaranteed loop through players only. You can then access their Character property if you need to interact with any part of their character such as for your distance check.

  • There’s no need to use GetPlayerFromCharacter if you incorporate the above advice because you will already have a variable pointing to the player. I’m not particularly sure why you would need to access another player’s PlayerGui anyhow, you should hand replicate if necessary.

  • Nested connections are going to result in a serious memory leak (performance drops or crashes!) especially since they’re being done in a for loop and it’s absolutely not where you want to go with this because if you want to add more dialogue it’s going to get significantly harder to maintain as well. You want your next button to be displaying text from a table of strings that should show instead of repeatedly connecting the button to show a new piece of text.

You’ll probably need to restructure the vast majority of this so that it’s maintainable and easy to add more dialogue prompts later into development of your experience.

In addition to what the person above said, one of your problems is you are putting a connection inside a connection inside a connection which is not a good thing to do.

Instead, you would either want to assign the connection to a variable and updating that variable with a new connection (which I dont really commend, because: ) or you can just simply increase a variable which is a number to determine which text to show within the same initial mouse button connection.

Like so:

local n = 1
MouseButton1Down:Connect(function()
local messages = {"A","B","C","D"}
	TextLabel.Text = messages[n]
	n += 1
	if n > #messages then n = 1 end
end)