Having problem with Player.Character

  1. What do you want to achieve?
    I would like to make a gui shirt giver

  2. What is the issue?
    I tried using this script:

script.Parent.MouseButton1Click:Connect(function(player)
	local shirtId = "http://www.roblox.com/asset/?id=3007867264"
	local char = player.Character or player.CharacterAdded:Wait()

	char.Shirt.ShirtTemplate = shirtId	
end)

the script is normal script in TextButton

and error appeared in output as: attempt to index nil with ‘Character’

I am new to Lua scripting and I would like some help as I do not understand what’s wrong with my scipt right now. Thank you in advance.

1 Like

Use game.Players.LocalPlayer for the player instead. I don’t think player is a valid argument of mouse button click

1 Like

the MouseButton1Click event doesn’t pass the player as an argument, use

 local player = game.Players.LocalPlayer -- the service will always exist at this point, since the local script will replicate after- GetService() is still canonical for getting services though
 local char = player.Character or player.CharacterAdded:Wait()
2 Likes

I tried changed to

script.Parent.MouseButton1Click:Connect(function()
	local shirtId = "http://www.roblox.com/asset/?id=3007867264"
	local player = game.Players.LocalPlayer 
 	local char = player.Character or player.CharacterAdded:Wait()
	
	char.Shirt.ShirtTemplate = shirtId	
end)

But it still getting atempt to index nil with ‘Character’

Make sure this is in a LocalScript rather than a regular script.

local Players = game:GetService('Players')
local player = Players.LocalPlayer
local shirtId = "http://www.roblox.com/asset/?id=3007867264"

script.Parent.Activated:Connect(function()
    local char = player.Character or player.CharacterAdded:Wait()
    local shirt = char:FindFirstChild('Shirt') or Instance.new('Shirt', char)
    shirt.ShirtTemplate = shirtId
end)

The reason is that If you use a ‘regular’/ server - script under StarterGui, then eventually it’ll be replicated under every player’s PlayerGui, the server won’t know about the script’s existence and the code in said script won’t run.

Alright, It’s worked. Thank you for helping me <3

1 Like

One thing to note; as far as I’m aware, changing the shirt on the client won’t replicate to the server. If you need it to replicate to the server (letting every client see that your shirt changed), let me know!

1 Like

Yes, I need everyone to see the shirt.

(post withdrawn by author, will be automatically deleted in 1 hour unless flagged)

You can make player something like this:

local player = script.Parent.Parent.howeverManyParentsYouNeed

Note that StarterGui is basically PlayerGui in the script, so player would be parent of PlayerGui, which will look like StarterGui

(hope this makes sense)

Edit: children of StarterGui are copied into each player’s PlayerGui when he joins the game

Edit2: this would be a server/normal script

Implement a mechanism to let it replicate to the server then, you could even change the ShirtTemplate on the server so every player sees the change.

Fire a remote and do it on the server if you insist on handling the UI part on the client.


Just addressing bad practice

instead of a long line for getting the player, just do Players.LocalPlayer for the local player.

@CrimsonForce

Just clarifying things, don’t call WaitForChild() on anything under Replicated Storage unless it’s guaranteed the script you’re calling from will be replicated first - it’s inefficient.

A debounce mechanism for the event firing would be good too, exploiters can spam remotes and crash servers.

Alrighty!

First, you’ll slightly edit your LocalScript as follows:

local RS = game:GetService('ReplicatedStorage')

local shirtId = "http://www.roblox.com/asset/?id=3007867264"
local event = RS:WaitForChild('ShirtEvent')

script.Parent.Activated:Connect(function()
    event:FireServer(shirtId) -- On this line, you can remove shirtId and simply define the id in the server script if you want to make this secure
end)

Then, you’ll make a Script inside of ServerScriptService like this:

local RS = game:GetService('ReplicatedStorage')
local event = RS:FindFirstChild('ShirtEvent') or Instance.new('RemoteEvent', RS)
event.Name = 'ShirtEvent'

event.OnServerEvent:Connect(function(player, shirtId) -- Once again, if needed you can simply define the id in this script to make it truly secure rather than depending on the id the client fires thru
    local char = player.Character or player.CharacterAdded:Wait()
    local shirt = char:FindFirstChild('Shirt') or Instance.new('Shirt', char)
    shirt.ShirtTemplate = shirtId
end)

Let me know if this works! Didn’t try it yet. :slightly_smiling_face:

Any related tutorial I can study about this?

Using a local script might not be the best all of the time, so I use a server script for most of my GUI so it will be harder for hackers to hack my remote events. (Like a coin giver GUI or something of the sort)

Do note that an exploiter can easily fire a remote in a while loop and cause the server to perform too many actions, this would crash a server almost instantly.

@Itttikorn yes, resources exist scattered everywhere, older posts on the forum can help you learn too.

2 Likes

Thanks for the info, I’ll add debouce to my remote events

I know Alvinblox has some tutorials about remote events on YouTube

It worked! Thank you everyone for helping me!