ServerScriptService attempt to index nil with 'Character'

So I made a script that when the player activates the tool it fires the remote event then the script in ServerScriptService runs but I get an error saying: ServerScriptService.TorsoChanger:3: attempt to index nil with ‘Character’. Here is my code:

local tool = script.Parent
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local torso = Character:WaitForChild("Torso")
local CharMesh = game:GetService("ReplicatedStorage").CharacterMesh
local Humanoid = Character:WaitForChild("Humanoid")
local CatEars = Instance.new("Accessory")
local Head = Character:WaitForChild('Head')
local ToolUsed = false
local Remote = game.ReplicatedStorage.TorsoChange


Remote.OnServerEvent:Connect(function(Player)
	if not ToolUsed then

		game:GetService("StarterGui"):SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)


		ToolUsed = true

		Character.isCat.Value = true
		print("Changed Value")

		print("anim1 loaded")
		Humanoid.WalkSpeed = 0
		local Character2 = tool.Parent

		local Anim = Instance.new("Animation")
		Anim.AnimationId = "http://www.roblox.com/asset/?id=6859909404"

		local LoadAnim = Character:WaitForChild("Humanoid"):WaitForChild("Animator"):LoadAnimation(Anim)
		LoadAnim:Play()

		wait(4)
		print("anim2 loaded")
		local Anim2 = Instance.new("Animation")
		Anim2.AnimationId = "http://www.roblox.com/asset/?id=6744582982"

		local LoadAnim2 = Character:WaitForChild("Humanoid"):WaitForChild("Animator"):LoadAnimation(Anim2)
		LoadAnim2:Play()

		wait(2)
		CatEars.Name = "FluffyEars"
		local handle = Instance.new("Part")
		handle.Name = "Handle"
		handle.Size = Vector3.new(1, 1, 1)
		handle.Parent = CatEars

		local HatFrontAttachment = Instance.new("Attachment")
		HatFrontAttachment.Name = "HatFrontAttachment"
		HatFrontAttachment.Position = Vector3.new(0, 0.6, 0)
		HatFrontAttachment.Parent = handle

		Head.face.Texture = 'rbxassetid://6780977849'

		local Earmesh = Instance.new("SpecialMesh")
		Earmesh.Name = "EarMesh"
		Earmesh.Scale = Vector3.new(1.05, 1.05, 1.05)
		Earmesh.MeshId = "rbxassetid://5437810334"
		Earmesh.TextureId = "rbxassetid://5457429757"
		Earmesh.Parent = handle

		Humanoid:AddAccessory(CatEars)

		local Mesh = CharMesh:Clone()
		Mesh.Parent = Character
		print("Added mesh")
		wait(1)
		Humanoid.WalkSpeed = 16
		game:GetService("StarterGui"):SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, true)
		wait(0.1)
		tool:Destroy()

		wait(1)

		ToolUsed = false

	end
end)

You’re defining"Character" Outside of the scope of the connection, the server cannot access a “LocalPlayer”
Solution:
Remove the “Player” from before the event, and move anything that references a player into the remote event where you were sent the player

Side note: You’re treating the server like the client, this will give you many issues as only one player can use the tool at a time while your variables are outside the connection scope

I dont know much about Remote events. How can I do This since almost all of the script is using LocalPlayer?

You do not need to do much, all you have to do is remove:

local Player = game.Players.LocalPlayer

Next, you need to move the following within your function (with the remote event):

local Character = Player.Character or Player.CharacterAdded:Wait()
local torso = Character:WaitForChild("Torso")
local Humanoid = Character:WaitForChild("Humanoid")
local Head = Character:WaitForChild('Head')

That’s all! The reason why you do this is because your remote event already takes in a parameter from who fired it, in this case the player. This will then be used by the server to reference your various variables you defined earlier.

1 Like

It works! Quick question. Im still learning scripting so can you explain why I had to remove and place some things within my function?

Sure thing!

So, at first, you were defining the LocalPlayer outside of the function. This will not work as LocalPlayer can only be accessed through a LocalScript. Players.LocalPlayer gives you the player with the LocalScript, and if you put it on a server script, the script does not know which player you are referencing as there are multiple within your game. This was the main issue with your code, and the rest was a domino effect.

Now, let’s look at your RemoteEvent function. As you may know, RemoteEvents can be fired from the server, from the client, etc (You can read more here if that sounds foreign: Bindable Events and Functions | Roblox Creator Documentation). Now, in this case, you were firing a RemoteEvent from the client to the server. When this happens, the script on the client in your case would be something like:

Remote:FireServer()

When you do this, the RemoteEvent fires to the server and an automatic parameter is already passed in, which you defined as Player in the following line:

Remote.OnServerEvent:Connect(function(Player)

This Player parameter is the same as the player who fired the RemoteEvent in the first place. If you put print(Player) within the function, you will see that the server prints out the player that activated the tool. Now, we have the Player, so all we have to do is use the Player parameter given to us already to make the rest of our script work.

All we then have to do is assign the character variable to Player.Character or Player.CharacterAdded:Wait(), as we will be using the Player parameter (again, which is directly referenced to the Player who fired it). This will then tell the script that we are looking for the player’s character directly. Next, the rest of your variables that we moved were directly referenced to the Character variable, so we just had to move that into the script so the script knows what the Character variable is.

Hope this made sense and helped you out. I tried my best to be as in-depth as possible, however, let me know if you still have any questions!

1 Like