I need help; when a person touches an object, a screen UI text fades in and out

It’s not much of a problem. Here’s what you need to do.

Step 1: Make a RemoteEvent inside of ReplicatedStorage
Step 2: Type this in the ServerScript

touch.Touched:Connect(function(hit)
    local player = game.Players:GetPlayerFromCharacter(hit.Parent)
    
    if player then
        game.ReplicatedStorage:WaitForChild("RemoteEvent_Name_Here"):FireClient(player)
    end
    
    touch:Destroy()
end)

Step 3: Add a LocalScript inside the text label and type this

local TweenService = game:GetService("TweenService")

game.ReplicatedStorage:WaitForChild("RemoteEvent_Name_Here").OnClientEvent:Connect(function()
    local textTween = TweenService:Create(script.Parent --[[Object]], TweenInfo.new(1) --[[Info]], {TextTransparency = 0} --[[Properties to change]])
    local textTween2 = TweenService:Create(script.Parent --[[Object]], TweenInfo.new(1) --[[Info]], {TextTransparency = 1} --[[Properties to change]])
    textTween:Play()
    textTween.Completed:Wait()
    task.wait(1) --Improved version of wait() [Check task library for more info]
    textTween2:Play()
    textTween.Completed:Wait()
end)

Note: I haven’t tested it in studio yet, but I’m really confident about it working.

Extras:

  1. Task Library
  2. TweenService
  3. RemoteEvent
1 Like

No. It’s not a glitch at all. The reason you’re getting this warning is because studio is very against global variables (it’s a really bad practice to use them anyway).
In order to fix your issue, declare a nil player variable just above the if character statement:

	local character = hit.Parent
	
	local player;
	if character then
		player = Players:GetPlayerFromCharacter(character)
	else
		warn("character not found")
	end

You could now also shorten this piece of code to avoid unnecessarily printing 2 warnings every time character fails:

	local character = hit.Parent
	local player = character and Players:GetPlayerFromCharacter(character) or nil; -- if character exists then call the GetPlayerFromCharacter function, otherwise set `player` as nil and terminate the function
	if not player then
				-- you could also print a warning here if you felt the need to
		return;	-- you can now safely remove the next `if player` statement
				-- as `return` will immediately terminate the function
	end

	-- the rest of the code should be here

^ but that’s just as a side note.

Also, as someone suggested below your post it would indeed be a way better idea to use tweenservice instead of 2 while loops.

1 Like

I’ve tried what you said, it didn’t work. It doesn’t give any output errors or anything. It just doesn’t work… :confused:

image

-- We cannot get the Players UI because the function hasn't been ran yet, so we cannot put the UI segment here.

-- What is the part that ``Touched:Connect(function()`` is being used on? We need to specify that.
local touch = workspace:WaitForChild("TextTouch") -- I'm assuming the script is a Child of the Part.

-- We need to get TweenService to properly tween in our UI. using Repeat until is not efficient when theres a service for this use case
local TweenService = game:GetService("TweenService")

-- Get the Players Service so we can find the player when they touch the part --
local PlayersService = game:GetService("Players")

-- Touched runs every time a player touches the part! Ouch! To prevent this, put a debounce (huge lag can occur if you don't!)
local db = false

touch.Touched:Connect(function(Part) -- we need to specify the part that hit it so we can define the User UI later.
	if not db then -- check to see if the debounce is false, if it is immediately set it to true so the script won't run again until it's declared false again
		if Part.Parent:FindFirstChild("Humanoid") then -- We need to put this here so our code doesn't execute when another part that isn't a player touches this
			db = true -- this stops runs every touch

			local Humanoid = Part.Parent:FindFirstChild("Humanoid") -- We want to locate our Humanoid for a very specific reason
			local Player = PlayersService:GetPlayerFromCharacter(Humanoid.Parent) -- We can get the Player to access their GUI.

			local UI = Player.PlayerGui:WaitForChild("MapTitle") -- simply replace the name of this string with the name of your ScreenGui
			local MapLabel = UI:WaitForChild("TextLabel") -- Finally we can get the TextObject so we can tween it to full transparency

			MapLabel.Text = "MapTest1" -- Call this whatever the name of the map is that you stepped into

			TweenService:Create(MapLabel, TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {TextTransparency = 0}):Play() -- What this does is makes a tween that makes the UI fade in.

			task.wait(3) -- an improved version of wait().

			TweenService:Create(MapLabel, TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {TextTransparency = 1}):Play() -- What this does is makes a tween that makes the UI out in.

			db = false -- set the debounce back to the false so the code can execute again
		end
	end 
end)

task.wait(0.01) -- changed to task.wait() for your own convenience.
touch:Destroy() -- This is because I'm making multiple parts for every map. So everytime they TP to another map, they spawn on the item and it activates. Then it deletes itself so they won't trigger it again. 

A server script wont work in starterplayerscripts. You need to replace it with a LocalScript.

1 Like

If it’s inside StarterPlayer it should be a LocalScript…

1 Like

uh… silly me. i forgot to revert it again to localscript because I was testing it out as a script on ServerScriptService. my bad…

2 Likes

It still has the same issue as this:

(press the quote to go on the original post)

The script doesn’t run at all? I recommend putting a print() statement at the top of each if then statement to see if it’s getting past the flags or not.

1 Like

-- What is the part that ``Touched:Connect(function()`` is being used on? We need to specify that.
local touch = workspace:WaitForChild("TextTouch") -- I'm assuming the script is a Child of the Part.

-- We need to get TweenService to properly tween in our UI. using Repeat until is not efficient when theres a service for this use case
local TweenService = game:GetService("TweenService")

-- Get the Players Service so we can find the player when they touch the part --
local PlayersService = game:GetService("Players")

-- Touched runs every time a player touches the part! Ouch! To prevent this, put a debounce (huge lag can occur if you don't!)
local db = false

touch.Touched:Connect(function(Part) -- we need to specify the part that hit it so we can define the User UI later.
	if not db then
		print("1")-- check to see if the debounce is false, if it is immediately set it to true so the script won't run again until it's declared false again
		if Part.Parent:FindFirstChild("Humanoid") then
			print("2")-- We need to put this here so our code doesn't execute when another part that isn't a player touches this
			db = true -- this stops runs every touch

			local Humanoid = Part.Parent:FindFirstChild("Humanoid") -- We want to locate our Humanoid for a very specific reason
			local Player = PlayersService:GetPlayerFromCharacter(Humanoid.Parent) -- We can get the Player to access their GUI.

			local UI = Player.PlayerGui:WaitForChild("MapTitle") -- simply replace the name of this string with the name of your ScreenGui
			local MapLabel = UI:WaitForChild("TextLabel") -- Finally we can get the TextObject so we can tween it to full transparency

			MapLabel.Text = "MapTest1" -- Call this whatever the name of the map is that you stepped into

			TweenService:Create(MapLabel, TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {TextTransparency = 0}):Play() -- What this does is makes a tween that makes the UI fade in.

			task.wait(3) -- an improved version of wait().

			TweenService:Create(MapLabel, TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {TextTransparency = 1}):Play() -- What this does is makes a tween that makes the UI out in.

			db = false -- set the debounce back to the false so the code can execute again
		end
	end 
end)

task.wait(0.01) -- changed to task.wait() for your own convenience.
touch:Destroy() -- unsure why you would want to destroy the part..? if you destroy it, it won't ever tell you the name of the map again!


It isn’t…

1 Like

Does the part disappear when you do this

local touch = workspace:WaitForChild("TextTouch")

? I wanted to help troubleshoot this issue myself but the part disappears upon calling this…

1 Like

Yes, it does disappear. 3030303030

1 Like

Sorry, I said “Does the part disappear for you.” because the part doesn’t show up for me when using that line. It only shows when I use a server script for this, and parent it to the part

1 Like

Well, I don’t see the part in Workspace when I join in the game. So, yes it does disappear. I accidently said appear but I edited it.

1 Like

This is really odd. It shouldn’t be destroying itself when :WaitForChild() is called. This method won’t ever work because it’s getting deleted.

Can a regular probably reading this make a bug report? This has never happened before.

1 Like

Should we try using a different method instead of touching the part? Like for example, the Atmosphere Hase colour. Cuz, every map, the atmosphere colour changes.

It strays from the original topic question. I’m trying out different things right now to see if I can figure out the issue.

1 Like

The part is destroying itself because there is a touch:Destroy on the bottom part of the code. Events do not yield meaning that when the game starts, the code after the Touched event will already run. What is the purpose of OP adding Destroy on the last line? If you want the part to be destroyed after it was touched, then consider putting the touched:Destroy() line after the db = false. But if you don’t need it to be destroyed, then just delete the line.

Edit: Also I haven’t read the whole post so I don’t know if I am talking about the right problem xD

2 Likes

Omg I’m such an idiot :man_facepalming:

I completely thought I put that destroy thing inside the function, not outside.

@althruist Please move that portion to the bottom where local db = false is declared again.

Big apologies.

2 Likes

Haha, it’s fine, we all make mistakes. Also did you make a typo? Since @althruist needs to put it in the line after:

db = false

not after the line:

local db = false

Because putting the :Destroy() after local db = false will destroy the part upon game starting

(Just clarifying since OP might be confused)

I meant to put it after, but I edited the final code all together. Also put the tweens in variables and put .Completed:Wait() for a smoother experience (so it doesn’t flicker and do that common tween glitch)

if not game:IsLoaded() then
	game.Loaded:Wait()
end

-- What is the part that ``Touched:Connect(function()`` is being used on? We need to specify that.
local touch = workspace.TextTouch -- I'm assuming the script is a Child of the Part.

-- We need to get TweenService to properly tween in our UI. using Repeat until is not efficient when theres a service for this use case
local TweenService = game:GetService("TweenService")

-- Get the Players Service so we can find the player when they touch the part --
local PlayersService = game:GetService("Players")

-- Touched runs every time a player touches the part! Ouch! To prevent this, put a debounce (huge lag can occur if you don't!)
local db = false

touch.Touched:Connect(function(Part) -- we need to specify the part that hit it so we can define the User UI later.
	if not db then
		print("1")-- check to see if the debounce is false, if it is immediately set it to true so the script won't run again until it's declared false again
		if Part.Parent:FindFirstChild("Humanoid") then
			print("2")-- We need to put this here so our code doesn't execute when another part that isn't a player touches this
			db = true -- this stops runs every touch

			local Humanoid = Part.Parent:FindFirstChild("Humanoid") -- We want to locate our Humanoid for a very specific reason
			local Player = PlayersService:GetPlayerFromCharacter(Humanoid.Parent) -- We can get the Player to access their GUI.

			local UI = Player.PlayerGui:WaitForChild("MapTitle") -- simply replace the name of this string with the name of your ScreenGui
			local MapLabel = UI:WaitForChild("TextLabel") -- Finally we can get the TextObject so we can tween it to full transparency

			MapLabel.Text = "MapTest1" -- Call this whatever the name of the map is that you stepped into

			local TweenIn = TweenService:Create(MapLabel, TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {TextTransparency = 0})
			TweenIn:Play()
			
			TweenIn.Completed:Wait()

			task.wait(3) -- an improved version of wait().

			local TweenOut = TweenService:Create(MapLabel, TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {TextTransparency = 1}) -- What this does is makes a tween that makes the UI out in.
			TweenOut:Play()
			
			TweenOut.Completed:Wait()

			touch:Destroy() -- we can replace this line ONLY with the destroy part instead, because we're never getting a chance to disable the debounce, since this code is only supposed to run once.
		end
	end 
end)

Feel free to remove this part

And put the touch variable back with :WaitForChild(). Either works, but I recommend :WaitForChild() more.

4 Likes