Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Player won't receive a GUI when they walk into a region?

I'm trying to make it so when a player walks into a specific region in the game, they will receive a GUI, although the player does obtain the GUI, it spams it multiple times. I've tried to check if the GUI is present, but I'm not 100% sure how to do that, any help would be great! Here's the script:

local Player = game.Players.LocalPlayer
repeat wait() until Player.Character
local Char = Player.Character
local RootPart = Char:WaitForChild("HumanoidRootPart")
local GUI = game.ReplicatedStorage.AIKeyboard



while wait() do
	local hit = workspace:FindPartOnRay(Ray.new(RootPart.Position, 		Vector3.new(0, -20, 0)), Char)
	if hit then
		if hit.Name == "Region" then
		for i,v in pairs(Player.PlayerGui:GetChildren()) do
			if v:IsA("ScreenGui") and v.Name == "AIKeyboard" then
				if v.Name == "AIKeyboard" then
				print("Keyboard is present")
			elseif v.Name ~= "AIKeyboard" then
				GUI:Clone().Parent = game.Players.LocalPlayer.PlayerGui
		end
	end
end
else
	for i,v in pairs(Player.PlayerGui:GetChildren()) do
		if v:IsA("ScreenGui") and v.Name == "AIKeyboard" then
		v:Destroy()
		end
	end
end
end
end

4 comments

0

Do you even know why "while wait() do" works, why are you using it, why not use something else, and please fix the indenting, and don't repeat wait() until Player.Character. That is stupid. Use events. Specifically, Player.CharacterAdded

0

I know what while wait() does, and I tried using other things than that but it doesn't work. And it is a local script, repeat wait() works for that and I see others using it, so where's your point there? No need to be insult someone over a question they're asking. Instead of saying "that's stupid" tell me exactly what to use. Most questions I've asked you've left small remarks that don't help at a

1

repeat wait() is an old implementation for what you are trying to do before Player.CharacterAdded event was added. Use the events because they are always going to be more efficient than your lua code.

0

"And it is a local script, repeat wait() works for that and I see others using it, so where's your point there?" is an appeal to popularity (https://yourlogicalfallacyis.com/bandwagon), and is not a logically sound argument for following some certain idiom. Millions of flies eat feces, does that mean feces are good? No. Same goes for the while wait() do idiom. Use while true do .. end. It's cl

2 answers

The problem is that you are using a for loop and checking if each object inside the PlayerGui is named "AIKeyboard". Let me show an example if you still haven't found the problem.

local AIKeyBoard = ScreenGui

for i,v in next, LocalPlayer.PlayerGui:GetChildren() do
    print(i, v.Name)
    if (v.Name == "AIKeyBoard") then
		print('no clone')
	else
		print('cloned')
		AIKeyBoard:Clone().Parent = PlayerGui
	end
end

Output:

1 Chat cloned 2 Freecam cloned 3 AIKeyBoard no clone 4 BubbleChat cloned

You are checking each individual object instead of scanning if it exists and cloning from there. You should be using :FindFirstChild() to see if the GUI object is there rather than running a for loop.

Alternatives

Instead of cloning, you can have "AIKeyBoard" already in the PlayerGui and make it visible when it a given area. I recommend raycasting on the client rather than the server because it could slow the server down (if used too fast).

You can also use Region3 to see if they are inside a box. The downside to this is that Region3 cannot be rotated.

Can't go wrong with Magnitude. Getting nearby players from a given point is something the server can calculate quickly and is a much more cleaner way to do this. Downside is that it can only be circle shaped.

Part.Touched works as well. If you add the correct debounces, it won't trigger the event too much. This can be rotated and it is probably the most efficient way you can do this.

Good luck with this!

Anytime you get something where it spams the desired result multiple times when you only want it to happen once, all you have to do is add a debounce. That would be the first thing I try in situations like this.

local debounce = false
while wait() do
	local hit = workspace:FindPartOnRay(Ray.new(RootPart.Position, 		Vector3.new(0, -20, 0)), Char)
	if hit then
		if not debounce then
			debounce = true
			if hit.Name == "Region" then
				for i,v in pairs(Player.PlayerGui:GetChildren()) do
					if v:IsA("ScreenGui") and v.Name == "AIKeyboard" then
						if v.Name == "AIKeyboard" then
							print("Keyboard is present")
						elseif v.Name ~= "AIKeyboard" then
							GUI:Clone().Parent = game.Players.LocalPlayer.PlayerGui
						end
					end
				end
			end
			debounce = false
		else
			for i,v in pairs(Player.PlayerGui:GetChildren()) do
			if v:IsA("ScreenGui") and v.Name == "AIKeyboard" then
				v:Destroy()
			end
		end
	end
end

My second suggestion would be to instead of having it create the gui and give it to the player would be to keep it in the player to begin with and just enable it or disable it whenever you enter or leave the region.

This discussion is preserved as it was. New answers, comments, and votes are closed.