How to Detect the Player's Character on Server?

I’m making a little simulator game as a side project. I’m making a shop on local, it works but, the points was taken out and when I grab a coin, all of the money that was spend returned. I wanted to make it on server. I tried using “LocalPlayer” but that was only for local. I tried using “GetPlayerFromCharacter” but I couldn’t find a possible way to even get the player’s character. I tried connecting with who ever clicks on it but it was nil. If you know a possible way then let me know.

Here is some of the code:

script.Parent.MouseButton1Click:Connect(function()
	local Player = script.Parent.Parent.Parent.Parent.Parent.Parent.Parent
	local Leaderstats = Player:WaitForChild('leaderstats')
	
	if Leaderstats.Gold.Value >= 10 then
		Sound.Reward:Play()
		Leaderstats.Gold.Value = Leaderstats.Gold.Value - 10
		Local.Character.Humanoid.WalkSpeed = Local.Character.Humanoid.WalkSpeed * 2
		wait(50)
		Local.Character.Humanoid.WalkSpeed = 20
	else
		Sound.NotEnough:Play()
	end
end)

the argument of your mouse click event returns the player who clicked it, so make a reference for it say player then do plr.Character

1 Like

I tried it one time, but it still said nil.
I tried printing who clicks it also said nil.

My bad. You need to cull it. Example

Local char = plr.Character or plr.CharacterAdded:Wait()

To add on to get the plr from it you do mouseDetector.MouseClick:Connect(function(plr)

Here is what I got:
[ Players.Nightmare4into96.PlayerGui.BoostShop.Frame.InnerFrame.SpeedBoosts.2Speed.Buy:5: attempt to index nil with ‘Character’]
Line 5 is the Variable char.

Is it a local script or server script?

I’m planning on making it a server script because the points that was taken out by a local script doesn’t save on the server/leaderboard.

Instead of player use local Player = game.Players.LocalPlayer or game.Players.PlayerAdded:Wait()

You can use remote events for something like this

LocalScript:

local remote = [insert path to remote here]

script.Parent.MouseButton1Click:Connect(function()
    remote:FireServer() -- send a request to the server
end)

Server Script:

local remote = [insert path to remote here]

remote.OnServerEvent:Connect(function(player) -- the player param is automatically passed
    local char = player.Character or player.CharacterAdded:Wait()
    -- code here
end)
1 Like

Try something like…

You could perhaps use one Remote Function to handle it on the server? Perhaps:

local Player = game.Players.LocalPlayer
local RemoteFunc = game.ReplicatedStorage.RemoteFunction

script.Parent.MouseButton1Down:Connect(function()
	local InvokeValue = RemoteFunc:InvokeServer()
	if InvokeValue == true then
		Sound.Reward:Play()
	else
		Sound.NotEnough:Play()
	end
end)

The server…

game.ReplicatedStorage.RemoteFunction.OnServerInvoke = function(Player)
    local Leaderstats = Player:WaitForChild("leaderstats")
    local Gold = Leaderstats:FindFirstChild("Gold")
    local Character = Player.Character
    if Gold ~= nil and Gold.Value >= 10 then
        Gold.Value = Gold.Value - 10
        if Character ~= nil then
            Character.Humanoid.WalkSpeed = Character.Humanoid.WalkSpeed * 2
        end
        local Value = Instance.new("BoolValue", Character)
        Value.Name = "EFFECT_VALUE"
        Value.Value = true
        game.Debris:AddItem(Value, 50) -- Waiting time

        Value.Changed:Connect(function(Property)
            if Property == "Parent" then
                if Character ~= nil then
                    Character.Humanoid.WalkSpeed = 20
                end
            end
        end)
        return true
    else
        return false
    end
end
2 Likes

This may not be related, but I thought that the player variable could be done like so:

local Player = game.Players.LocalPlayer

That will only work in LocalScripts, game.Players.LocalPlayer

1 Like