I’m currently doing work for a large group and I created something that works in my testing game, works in studio, works with all my tests. But when it gets put into their game it doesn’t work.
Here’s the script:
script.Parent.Touched:Connect(function(hit)
local player = hit.Parent
local plr = game.Players:FindFirstChild(player.Name)
local JacksonsShop = game.ServerStorage:WaitForChild("GUIs",100):FindFirstChild("JacksonsShop"):Clone()
JacksonsShop.Parent = plr:WaitForChild("PlayerGui",100)
end)
script.Parent.TouchEnded:Connect(function(hit)
local plr = game.Players:FindFirstChild(hit.Parent.Name)
plr.PlayerGui:WaitForChild("JacksonsShop",100):Destroy()
end)
It works 100% of the time in my test game, however when put in the actual game I get these errors:
At first I thought it had to do with the script running before the game loaded so I destroyed the script by waiting for nearly everything. At this point though, I just don’t know.
Please drop help below.
edit: the problem was that for some reason the script could not access ServerStorage.GUIs even though it itself was a server script. I moved the GUI into ReplicatedStorage and the issue fixed itself.
This error happens because plr is nill, you should use game.Players:GetPlayerFromCharacter().
The script:
script.Parent.Touched:Connect(function(hit)
local player = hit.Parent
local plr = game.Players:GetPlayerFromCharacter(player)
if plr then
local JacksonsShop = game.ServerStorage:WaitForChild("GUIs",100):FindFirstChild("JacksonsShop"):Clone()
JacksonsShop.Parent = plr:WaitForChild("PlayerGui",100)
end
end)
script.Parent.TouchEnded:Connect(function(hit)
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
if plr then
plr.PlayerGui:WaitForChild("JacksonsShop",100):Destroy()
end
end)
I took your advice and all of the other errors have subsided.
Now the only issue is this:
here is the re written script:
> local GUIs = game.ServerStorage:WaitForChild("GUIs")
>
> function TouchStart(hitPart)
> local character = hitPart.Parent
> if character:IsA('Model') then
> local player = game.Players:GetPlayerFromCharacter(character)
> local gui = GUIs:FindFirstChild("JacksonsShop"):Clone()
> gui.Parent = player:WaitForChild("PlayerGui")
> end
> end
>
> function TouchEnd(hitPart)
> if hitPart.Parent:IsA('Model') then
> local player = game.Players:GetPlayerFromCharacter(hitPart.Parent)
> local playerGui = player:WaitForChild("PlayerGui")
> if playerGui:FindFirstChild("JacksonsShop") ~= nil then
> local gui = playerGui:FindFirstChild("JacksonsShop")
> gui:Destroy()
> end
> end
> end
>
> script.Parent.Touched:Connect(TouchStart)
> script.Parent.TouchEnded:Connect(TouchEnd)
edit: oh yeah I understand that it’s only a warning, but it’s just simply not working
It seems like GUIs is being set to nil. I know you already fixed this issue above, but I have a theory (it’s probably wrong, but I’m guessing you are willing to try anything at this point).
First, try putting your script in ServerScriptService. Not that it makes a difference (in theory), but theory right now is playing against us.
Next I suggest you use GetService("ServerStorage") instead of using the . . Same thing for game:GetService(“Players”) but that doesn’t seem to cause issues. Regardless, at least try it for ServerStorage.
I am just playing on a (bad) hunch that you are getting a funny interaction with ServerStorage. As for your recent change (putting the GUIs folder in the script) I don’t know what code you changed after you put it in there. That would be helpful to understand the new problems you are having
For this I would recommend putting it in ReplicatedStorage.
Please note this is a quick type up.
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GUIs = ReplicatedStorage:WaitForChild("GUIs")
script.Parent.Touched:Connect(function(Obj)
local Player = Players:GetPlayerFromCharacter(Obj.Parent)
if Player ~= nil then else return end
if Player:WaitForChild("PlayerGui"):FindFirstChild("JacksonsShop") == nil then
local ShopGui = GUIs["JacksonsShop"]:Clone()
ShopGui.Parent = Player:WaitForChild("PlayerGui")
end
end)
script.Parent.TouchEnded:Connect(function(Obj)
local Player = Players:GetPlayerFromCharacter(Obj.Parent)
if Player ~= nil then else return end
if Player.PlayerGui:FindFirstChild("JacksonsShop") ~= nil then
Player.PlayerGui["JacksonsShop"]:Destroy()
end
end)
The part you said don’t make much changes in speed or anything else, but it waits so the service is loaded. If he puts the GUI in the script, with this script he can solve this problem:
function TouchStart(hitPart)
local character = hitPart.Parent
if character:IsA('Model') then
local player = game.Players:GetPlayerFromCharacter(character)
local gui = script.GUIs:FindFirstChild("JacksonsShop"):Clone()
gui.Parent = player:WaitForChild("PlayerGui")
end
end
function TouchEnd(hitPart)
if hitPart.Parent:IsA('Model') then
local player = game.Players:GetPlayerFromCharacter(hitPart.Parent)
local playerGui = player:WaitForChild("PlayerGui")
if playerGui:FindFirstChild("JacksonsShop") ~= nil then
local gui = playerGui:FindFirstChild("JacksonsShop")
gui:Destroy()
end
end
end
script.Parent.Touched:Connect(TouchStart)
script.Parent.TouchEnded:Connect(TouchEnd)
this is much simpler and why you put a random else?
If he puts the GUIs in the script, and the script in ServerScriptService then the client can’t get it. If you put it in the workspace or ReplicatedStorage any exploiter may access the shop from anywhere. So, putting the GUIs in the script and the script in ServerScriptService is the most secure way.
local SHOP = game.ServerStorage:WaitForChild("GUIs"):WaitForChild("JacksonsShop")
local chars = {}
script.Parent.Touched:Connect(function(hit)
local player = game.Players:FindFirstChild(hit.Parent.Name)
if not player or chars[hit.Parent] then return end --If player doesn't exist OR if the player already has the shop gui
local JacksonsShop = SHOP:Clone()
chars[hit.Parent] = JacksonsShop
JacksonsShop.Parent = player.PlayerGui
end)
script.Parent.TouchEnded:Connect(function(hit)
local JacksonsShop = chars[hit.Parent]
if JacksonsShop then
JacksonsShop:Destroy()
chars[hit.Parent] = nil
end
end)
But touchEnded events like these are really scetchy tho, sometimes it doesnt call TouchEnded at all.
This should work tho.
Not reverses the logical state of an operand, ~= checks for negation of equality. Simplicity is a subjective thing and can differ between people, so it’s fine to use either one. The hanging else is the only bit that’s bad to include; blank cases in an if statement aren’t really savory.