Character variables after respawn

In my game there are a lot of character based variables that become broken if a player resets or dies. This is because the character is replaced and so the old variables are no longer valid. I have a way to combat this but it doesn’t seem to work in local scripts.

I was thinking a solution might be to do it in a module that then fires a remote to all scripts based around the player character, but it seems like there’s probably an easier way to achieve the same thing.

local plr = Players.LocalPlayer

local char = plr:WaitForChild("Character")
local hum = char:WaitForChild("Humanoid")
local plrbody = char:WaitForChild("HumanoidRootPart") or char:WaitForChild("Torso")

plr.CharacterAdded:Connect(function(updatedChar)
	warn("New character added!")
	char = updatedChar
	hum = char:WaitForChild("Humanoid")
	plrbody = char:WaitForChild("HumanoidRootPart") or char:WaitForChild("Torso")
end)
4 Likes

you can use the :Wait() for the CharacterAdded event and put it in a varible like this;

local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait() -- if Player.Character is nil then it will wait (or yield) the script till CharacterAdded is fired?

local Humanoid = Character:WaitForChild("Humanoid")
local plrBody =  char:WaitForChild("HumanoidRootPart") or char:WaitForChild("Torso")

here it will explain what Event:Wait() is.

1 Like

That’s what I used before, but my script returned errors after the char was replaced after death. I assumed it was because the variable didn’t change after the char changed, but maybe it’s a different issue then.

1 Like

well what was the error? and how ya script looked like?

1 Like

local plr = Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local plrbody = char:WaitForChild("HumanoidRootPart")

It works fine until I jump off the map, at which point this error message shows. The same thing happens with ‘or char:WaitForChild(“Torso”)’, so it has to be to do with the Char changing, or maybe being temporarily unavailable and therefore messing up the variables.

1 Like

why dont you use :FindFirstChild instead? i yet don’t know why that happens… does it happen when u reset too? also just check if its not nil when using FindFirstChild? i was reading dev forum whom had the same problem maybe but it dont look helpfull devForumLink

1 Like

That’s so weird. I used :FindFirstChild and it worked, but only if I put a wait() first.

wait(1)
local plr = Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local plrbody = char:FindFirstChild("HumanoidRootPart")
1 Like

hm i would agree… also quick question where is the local script located?

1 Like

In a tool in StarterPack, could that be an issue?

1 Like

Try this:

local plr = Players.LocalPlayer

local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")
local plrbody = char:WaitForChild("HumanoidRootPart") or char:WaitForChild("Torso")

plr.CharacterAdded:Connect(function(updatedChar)
	warn("New character added!")
	char = updatedChar
	hum = char:WaitForChild("Humanoid")
	plrbody = char:WaitForChild("HumanoidRootPart") or char:WaitForChild("Torso")
end)
1 Like

If you don’t want the values removed, why don’t you add them into the Player instance?

That didn’t work. I thought about it and it could be because I have a while loop later on in the script?

Could you explain what you mean?

The character is a property of the player, not a child.

I recommend creating a separate function that controls whatever you’re trying to do, managing connections would be easier. Something like this:

local localChar

local function getBody(character)
    localChar = updatedChar
	hum = char:WaitForChild("Humanoid")
	plrbody = char:WaitForChild("HumanoidRootPart") or char:WaitForChild("Torso")
end)

getBody(plr.Character or plr.CharacterAdded:Wait()) -- get it when the player first joins
pls.CharacterAdded:Connect(getBody)

I also saw from the thread that you were trying to do this from a tool, when the player died you were having issues. You could probably navigate it like this:

local function doControl(player)
    local character
    player.CharacterAdded:Connect(function(newCharacter)
        character = newCharacter
        print('New character assigned to variable', newCharacter)
    end) 
    character = player.Character or player.CharacterAdded:Wait()
    print('Initial variable value ', character
end

My apologies, I misunderstood what you mean. I thought you meant you had like instances for variables. Disregard what I said.

1 Like

I’ll try both. Could you explain the second function? As in where would I use it vs the other function? I’m assuming localChar is the char variable.

Also, why would it work with :FindFirstChild(), but not :WaitForChild()?

Edit: It didn’t work with the functions provided.

It shouldn’t have worked with :FindFirstChild unless there was an actual child of the player called Character.

The second function was an example of how you would go about getting the character of another player if they died.

Could you elaborate on what you’re trying to do specifically?

1 Like

Yeah, sorry, I should have been more specific. I was talking about char:WaitForChild(“HumanoidRootPart”) vs FindFirstChild(), and how this worked fine:

wait(1)
local plr = Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local plrbody = char:FindFirstChild("HumanoidRootPart")

But this broke my script:

local plr = Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local plrbody = char:WaitForChild("HumanoidRootPart")

I’m applying your function to a script which causes the player to be able to pick up items if they press ‘e’. I’m doing this via a coroutine and while loop later on in the script. Could this be an issue? I tried placing a .CharacterAdded inside the while loop as well but it didn’t help.

At the moment I get this error message immediately when I use your first function:

local plr = Players.LocalPlayer

local char 
local hum 
local plrbody 

local function getBody(updatedChar)
	char = updatedChar
	hum = char:WaitForChild("Humanoid")
	plrbody = char:WaitForChild("HumanoidRootPart") or char:WaitForChild("Torso")
end

getBody(plr.Character or plr.CharacterAdded:Wait()) 
plr.CharacterAdded:Connect(getBody)

Sorry for the late response, was busy.

First thing, that should have worked, doesn’t appear Either :WaitForChild() or :FindFirstChild(). Could you provide a .rbxl/rbxm file to see if I can reproduce it?

Second thing, I see what you mean now. Your script is in a tool, correct? Also, the e to pickup should only appear when the tool is equipped, right?

I’m thinking that you could go about controlling the tool in a different way. Instead of a localscript inside of the tool, you could do something inside of StarterPlayerScripts or StarterCharacterScripts. Let me know if you’re interested in this option and I’ll try my best to help you rewrite.

Anyway, try and see if this helps or gives another issue.

local players = game:GetService('Players')

local plr = players.LocalPlayer

local char, hum, plrBody

local function getBody(updatedChar)
    hum = updatedChar:WaitForChild('HumanoidRootPart')
    plrBody = updatedChar:WaitForChild('HumanoidRootPart') or char:WaitForChild('Torso')
    char = updatedChar
end

getBody(plr.Character or plr.CharacterAdded:Wait())
plr.CharacterAdded:Connect(getBody)
1 Like

I’ll put a Pastebin of the full script below. I made it a while ago when I was less proficient so I would definitely do things differently now. It works as intended though. I just want to know why your function (which in my opinion is a better and safer way of getting the character than what I’ve used) doesn’t work.

https://pastebin.com/FBfBqwZ6

If you don’t see anything immediately obvious in that I could probably move some assets to another file to try and replicate it, but everything is currently in a group edit studio session, so could be quite hard.

1 Like