Self._player is nil?

Hello everyone. I’m experiencing an issue. Apparently, self._player is nil in my function, however, above, I’ve had set it to the player’s character. Notice any problems?

local Knit = require(game.ReplicatedStorage.Knit)
local Maid = require(Knit.Util.Maid)
local DataStore = require(game.ServerScriptService.DataStore)

local Players = game:GetService("Players")

local Egg = {}
Egg.__index = Egg

Egg.Tag = "Egg"

function Egg.new(instance)
	local self = setmetatable({}, Egg)
	self._maid = Maid.new()
	self._player = instance.Parent
	self.crackLevel = 0
	return self
end

function Egg:Init()
	local equippedEgg = DataStore:ReturnEquippedEgg(Players:GetPlayerFromCharacter(self._player))
	if equippedEgg == nil then
		local starteregg = game.ServerStorage.Eggs:WaitForChild("StarterEgg")
		local default = starteregg:WaitForChild("Default")
		
		Egg:LoadChar(default)
	else
		local serverStorageEgg = game.ServerStorage.Eggs:WaitForChild(equippedEgg)
		local default = serverStorageEgg:FindFirstChild("Default")

		if default then
			Egg:LoadChar(default)
		else
			assert("Error: Couldn't find the default egg character")
		end
	end
end

function Egg:LoadChar(egg)
	local newEgg = egg:Clone()
	newEgg.Parent = workspace
	
	print(self._player)

	newEgg:SetPrimaryPartCFrame(CFrame.new(self._player.HumanoidRootPart))

	newEgg.Name = self._player.Parent.Name

	self._player:Destroy()

	self._player = newEgg
end

function Egg:Crack()
	local character = self._player:FindFirstChild("Character")
	local equippedEgg = DataStore:ReturnEquippedEgg()
	self.crackLevel = self.crackLevel + 1
	if self.crackLevel > 5 then
		print("Player supposed to die!")
	else
		local eggModel = equippedEgg:FindFirstChild(self.crackLevel)
		
		if eggModel then
			print("Found egg model!")
			Egg:LoadChar(eggModel)
		end
	end
end

function Egg:Destroy()
	self._maid:Destroy()
end

return Egg

Might be a garbage-in-garbage-out (GIGO) type of situation. Egg.new should ensure it is not being given garbage, as it currently doesn’t produce an error if it’s given garbage, and that might be your problem:

function Egg.new(instance)
    assert(instance.Parent:IsA("Player")) -- Or whatever else you expect this to be
    -- ...

Try changing your Egg:Crack() function to

function Egg:Crack()
	local character = self._player:FindFirstChild("Character")
	local equippedEgg = DataStore:ReturnEquippedEgg()
	self.crackLevel = self.crackLevel + 1
	if self.crackLevel > 5 then
		print("Player supposed to die!")
	else
		local eggModel = equippedEgg:FindFirstChild(self.crackLevel)
		
		if eggModel then
			print("Found egg model!")
			self:LoadChar(eggModel)
		end
	end
end

Oops, forgot to tell. the self._player is the player’s character! The problem is that the self._player is nil

Thanks for the reply, but it isn’t the solution to my problem. It still prints nil

I think self._player and the self.humRootPart I created just has the names stored in it, that’s why this isn’t working

Never mind, both of them print nil. Any more suggestions?

I am not sure if you implemented my reply, but did you try changing the Egg:Crack() method to the following code?

function Egg:Crack()
	local character = self._player:FindFirstChild("Character")
	local equippedEgg = DataStore:ReturnEquippedEgg()
	self.crackLevel = self.crackLevel + 1
	if self.crackLevel > 5 then
		print("Player supposed to die!")
	else
		local eggModel = equippedEgg:FindFirstChild(self.crackLevel)
		
		if eggModel then
			print("Found egg model!")
			self:LoadChar(eggModel) -- Here
		end
	end
end

The difference between this and your Egg:Crack() function is on the line denoted by my comment. You are calling the class’s method instead of the object’s method. I think this might be a reason for your error.

Never mind, it works! Thanks, but I still can’t load the character

edit: it gives an infinite yield in game.Workspace:WaitForChild(self._player)

edit 2: tried printing and it doesn’t print after the waitforchild line

Can you show us the script containing the WaitForChild function?

local Knit = require(game.ReplicatedStorage.Knit)
local Maid = require(Knit.Util.Maid)
local DataStore = require(game.ServerScriptService.DataStore)

local Players = game:GetService("Players")
local CollectionService = game:GetService("CollectionService")

local Egg = {}
Egg.__index = Egg

Egg.Tag = "Egg"

local eggs = {}

function Egg.new(instance)
	local self = setmetatable({}, Egg)
	self._maid = Maid.new()
	self._player = Players:GetPlayerFromCharacter(instance.Parent)
	self.crackLevel = 0
	return self
end

function Egg:Init()
	local equippedEgg = DataStore:ReturnEquippedEgg(self._player)
	if equippedEgg == nil then
		local starteregg = game.ServerStorage.Eggs:WaitForChild("StarterEgg")
		local default = starteregg:WaitForChild("Default")
		
		self:LoadChar(default)
	else
		local serverStorageEgg = game.ServerStorage.Eggs:WaitForChild(equippedEgg)
		local default = serverStorageEgg:FindFirstChild("Default")

		if default then
			self:LoadChar(default)
		else
			error("Error: Couldn't find the default egg character")
		end
	end
end

function Egg:LoadChar(egg)
	local character = game.Workspace:WaitForChild(self._player)
	local newEgg = egg:Clone()
	newEgg.Parent = workspace
	
	print("Parented egg to workspace")

	newEgg:SetPrimaryPartCFrame(CFrame.new(0, 0, 0))

	newEgg.Name = self._player

    character:Destroy()

	character = newEgg
end

function Egg:Crack()
	local equippedEgg = DataStore:ReturnEquippedEgg(self._player)
	self.crackLevel = self.crackLevel + 1
	if self.crackLevel > 5 then
		print("Player supposed to die!")
	else
		local eggModel = equippedEgg:FindFirstChild(self.crackLevel)
		
		if eggModel then
			print("Found egg model!")
			self:LoadChar(eggModel)
		end
	end
end

function Egg:Destroy()
	self._maid:Destroy()
end

local EggAddedSignal = CollectionService:GetInstanceAddedSignal(Egg.Tag)
local EggRemovedSignal = CollectionService:GetInstanceRemovedSignal(Egg.Tag)

local function EggAdded(instance)
	if instance:IsA("Part") then
		if instance.Parent:IsA("Model") then
			eggs[instance.Parent] = Egg.new(instance)
		end
	end
end

local function EggRemoved(instance)
	if eggs[instance.Parent] then
		eggs[instance.Parent]:CleanUp()
		eggs[instance.Parent] = nil
	end
end

for _,inst in pairs(CollectionService:GetTagged(Egg.Tag)) do
	EggAdded(inst)
end

EggAddedSignal:Connect(EggAdded)
EggRemovedSignal:Connect(EggRemoved)

return Egg

The same script, just with a couple more lines

edit: print(“Parented egg to workspace”) doesn’t get printed.

It seems the issue here is because you changed what self._player is equal to. In your original post, self._player is set to the player character. However, in this new script, self._player is set to the actual player. Thus, when you call the WaitForChild method of the workspace, the computer looks for player as a child of the workspace. Obviously, this cannot be the case since any player should be a child of game.Players, not game.Workspace. Can you clarify whether self._player is supposed to be the player or the workspace?

It’s actually the player, that’s why I tried to find the character in the workspace. Do I need to create something like self._character = instance.Parent?

Okay, turns out that works. Thanks for the help! I’m getting another error, but I’m sure I can fix that

1 Like

If line 43 of your module script is aimed to get the character of your player, simply do

local character = self._player.CharacterAdded:wait()

Oh, okay. Glad you were able to resolve your issue. Good luck on your project!

1 Like

WaitForChild receives a string as its argument which is the instance name, you have to do:

game.Workspace:WaitForChild(self._player.Name)

Also, after reading your code I got confused about what self._player is, you are doing:

Players:GetPlayerFromCharacter(self._player)

Which means that _player is the Player’s Character, but you are also doing:

local character = self._player:FindFirstChild("Character")`

Which means that _player is the Player, and it’s also wrong because the Player’s Character is not a child of Player but of Workspace.

You do:

newEgg:SetPrimaryPartCFrame(CFrame.new(self._player.HumanoidRootPart))

newEgg.Name = self._player.Parent.Name

Which is wrong again, because if _player is the character then _player.Parent is the Workspace. And you can’t pass HumanoidRootPart to CFrame.new because it’s an instance.

I’ve changed the player to the player in the players service. I now have a self._character and it works just fine. Thanks for giving your time to make this reply anyway!