I’ve tested something myself and it works. I’ll try my best to explain the process i did and also link resources below in-case you would like to read more.
What i did:
I created a ScreenGui and only added the TextButton gui element as it’s child.
I renamed the TextButton to “DontShowAgainButton”.
I then added a LocalScript inside of the TextButton and added the following code:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GuiElementsEvent = ReplicatedStorage:WaitForChild("GuiElements")
local localPlayer = Players.LocalPlayer
if not localPlayer then
Players:GetPropertyChangedSignal("LocalPlayer"):Wait()
localPlayer = Players.LocalPlayer
end
local PlayerGui = localPlayer:FindFirstChildOfClass("PlayerGui") or localPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local DontShowAgainButton = ScreenGui:WaitForChild("DontShowAgainButton")
DontShowAgainButton.Activated:Connect(function()
if localPlayer:GetAttribute("DisablePrompt") ~= true or nil then
GuiElementsEvent:FireServer("DontShowAgain", true)
end
end)
What i’m doing with this code is i’m getting the ScreenGui from the PlayerGui itself and referencing the “DontShowAgainButton” on the ScreenGui.
Then i’m checking if the player has the attribute “DisablePrompt” and if it’s set to true to make sure the player didn’t already press the button and spam fire the event.
I then pass in 2 arguments, the first argument is “DontShowAgain” and the second argument is a boolean value which is true. I do this normally with my scripts and i normally limit the usage of a lot of RemoteEvents so i keep it organized by checking its first argument for it’s “request”.
I created a Script in ServerScriptService and for safety measures i set it’s RunContext to Server.
I then added the following code:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")
local dontShowAgainDataStore = DataStoreService:GetDataStore("PlayerData", "DontShowAgainGui")
local GuiElementsEvent = ReplicatedStorage.GuiElements
Players.PlayerAdded:Connect(function(player: Player)
local playerUserId = "Player_" .. player.UserId
local PlayerGui = player:FindFirstChildOfClass("PlayerGui") or player:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local success, elementStatus = pcall(dontShowAgainDataStore.GetAsync, dontShowAgainDataStore, playerUserId)
if success then
if elementStatus == false then
ScreenGui.Enabled = true
elseif elementStatus == true then
ScreenGui.Enabled = false
ScreenGui:Destroy()
end
else
player:Kick("Failed to load DataStore, please rejoin")
return
end
end)
GuiElementsEvent.OnServerEvent:Connect(function(player: Player, request: string, requestBool: boolean)
if typeof(player) ~= "Instance" then return end
if typeof(request) ~= "string" then return end
if typeof(requestBool) ~= "boolean" then return end
local playerUserId = "Player_" .. player.UserId
local PlayerGui = player:FindFirstChildOfClass("PlayerGui") or player:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
if request == "DontShowAgain" and requestBool == true then
local success, updatedStatus
success, updatedStatus = pcall(dontShowAgainDataStore.SetAsync, dontShowAgainDataStore, playerUserId, true)
if success == true then
ScreenGui.Enabled = false
ScreenGui:Destroy()
player:SetAttribute("DisablePrompt", true)
print("Successfully saved data for", player.Name)
elseif success == false then
repeat
success, updatedStatus = pcall(dontShowAgainDataStore.SetAsync, dontShowAgainDataStore, playerUserId, true)
until
success == true
end
end
end)
What i’m doing here is i’m creating the DataStore called “PlayerData” with it’s scope “DontShowAgainGui”.
Then whenever a player is added, i would create the key which is the playerUserId variable. (It’s essential to set it as the players UserId as it’s easy to check that specific players data, it doesn’t change and it’s easy to identify and remove it in the case of a Right-To-Erasure request) I also referenced the ScreenGui that contains the prompt we want to remove. I then get the data from the scope (DontShowAgainGui) using a pcall and do some checks.
If the call ran successfully, we check the status/data of the player. If the call was unsuccessful, we would kick the player and return nothing to stop the function from running further. We kick the player to ensure their data loads successfully and doesn’t cause any issues.
If it ran successfully, the data we check will be a boolean value we sent from the RemoteEvent on the LocalScript earlier.
If the status is false, we would enable the ScreenGui for the player. If the status is true, we would disable the ScreenGui and destroy it from the PlayerGui to save memory and space.
For the OnServerEvent i passed in 2 extra arguments like the ones we sent to the server. A request which is a string and a requestBool which is a boolean value.
I then do some checks for those arguments as an extra layer of security to ensure the data that’s sent is correct using typeof.
After that i would create the playerUserId variable again and reference the ScreenGui from PlayerGui.
Then i’d check for the request and the requestBool to see if they match what’s being sent from the client. If they do match, it would save the players data for that scope as true, disable and destroy the ScreenGui, and set the players attribute to true to ensure the player can’t spam the event if they somehow still have the gui element.
If it wasn’t a success, it would try to repeatedly save until it’s a successful save.
Resources:
DataStore
DataStore Scopes
RemoteEvents
RemoteEvents and Callbacks
Client-Server Runtime
pcall (Protected Call)
typeof
I hope this helps and makes you understand a bit more on how you can do something like this. It’s not the best but that’s how i typically write my code and organize them, especially in a short amount of time. I tested it and it works and also the attribute is only in one game instance, it doesn’t save with the datastore.