You can try to add an if statement that checks if the player exists then prompt the purchase.
Also when prompting a purchase you should always call it from a local script, because it will show the prompt on the player’s screen.
From what I perceived, you are using a textbutton on a part and using the MouseButton1Click event for your script. This may not work because the event cannot fetch which player is clicking, so the script thinks its nil and gives you that error. A better option is to use a ClickDetector on that part because you can use the MouseClick event and get the player since it can give you the player.
This is a common mistake I see when trying to make SurfaceGUI’s, and it’s a simple solution.
First, move your SurfaceGui into StarterGui:
Then set it’s Adornee property to the part you’d like it to display on.
Now we can script it like you would normally script a TextButton. Add a RemoteEvent to ReplicatedStorage called “PromptPurchase”, and link to it through the TextButton script.
Whether possible or not it’s always been a habit of mine to send purchase data to the server as I use an excessive custom analytics module that collects all of the data, besides I like having all of my purchase handling in one script, that being both prompting and processing purchases.
Here is what I think is the solution:
You can start by doing what @S_maritan says.
Then we will make it so that when the button is clicked, it will prompt the purchase
Then create a script, so we can hook this prompt with the server.
game:GetService("MarketplaceService").ProcessReceipt = function(reciept) --Here we are hooking the client code with the server
for _, player in pairs(game.Players:GetPlayers()) do --Then we are looping through all the players in-game
if player.UserId == reciept.PlayerId and receipt.ProductId == productId then --If the player id is the same id of the player that purchased the product then we continue
--Add code to execute when player purchases product
end
end
end