Weird workspace behavior

So I was trying to get the player Instance returned by the hit parameter of the Touched event from the workspace but it turns out that for some weird reason I can’t get it from workspace service but it returns nil whenever I do that and that means that it doesn’t exist when it clearly does so instead I have to reference it by itself to get the returned result so why does that happen?

I will use a simple script that is enough to confirm this so you can see for yourself:

-- No one can access this script because it's located in ServerScriptService and it's a place where exploiters/normal players can't see what's inside
local brick = workspace:WaitForChild("Part") -- workspace is a built-in reference to the Workspace service

--[[ 
 Now we create a Touched event for the brick that keeps listening for when somebody touches the brick
 until we disconnect the connection that is 'returned' by the Touched connection that we created
--]]
local brickTouchedConn
brickTouchedConn = brick.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChildOfClass("Humanoid") then -- The player's character is NOT considered a userdata so I don't have to use tostring() in order to use it for string concatenating
		local plrCharacter = hit.Parent
		local plrCharacterbyWorkspace = workspace:FindFirstChild(hit.Parent)
		brick.Transparency = 0.5
		print(tostring(plrCharacterbyWorkspace)) -- This is nil but why does it work without finding it by getting the workspace first?
		print(tostring(plrCharacter).. " just changed " ..tostring(brick).. "'s Transparency to " ..tostring(brick.Transparency).. "!")
		brickTouchedConn:Disconnect() -- The Touched event is no longer listening for when somebody touches it because we just disconnected it
	end
end)

And here’s an image of the returned results by the script:

Results

As you can see it prints nil when I try to find the player Instance from the workspace service and that means that it DOESN’T exist but it clearly exists because when it printed my player Instance later so why does this weird behavior of the workspace service happen?

1 Like

Youre finding a BasePart instead do

local plrCharacterbyWorkspace = workspace:FindFirstChild(hit.Parent.Name)

NOT

local plrCharacterbyWorkspace = workspace:FindFirstChild(hit.Parent)
1 Like

Could you give me a more broad explanation as to why I can get it by simply saying hit.Parent instead of hit.Parent.Name which is exactly what I did for the second print while for the workspace service I have to do hit.Parent.Name, I still don’t understand why this weird behavior tends to happen without getting the Name property of the Instance which I’m trying to reference?

Spoon feeding code won’t make us learn anything, instead it will create more confusion.

1 Like

Cause your trying to find something in workspace that it can’t like the players arm, but if you say “hit.Parent.Name” it will look in workspace for the players name.

EDIT: and then it will find the players character

4 Likes

So what you are trying to tell me is that hit.Parent contains an Instance which is clearly what touched the brick but when I say hit.Parent.Name I’m trying to get a string containing that Instance’s Name property I understand that but I still have some questions.

What I’m trying to actually understand here is why does it work when I say hit.Parent instead of workspace:FindFirstChild(hit.Parent.Name), that still works WITHOUT getting the Name property of the Instance which is a string so that means that it still works with an Instance so why does it not work when I get it via the workspace?

@lualeet The same above goes for you, that is still what I’m not trying to understand here.

hit.Parent is simply the same result you’d get as finding something with hit.Parent’s name in workspace. Is there some reason for you needing to use FindFirstChild?

2 Likes

The reason :FindFirstChild doesn’t work with an instance is simply because it is made that way, if you already have an instance you have no reason at all to search for it.

1 Like

Instance:FindFirstChild() works with Instances, the reason I’m using Instance:FindFirstChild() is because if the brick doesn’t exist then the entire script won’t stop because it couldn’t find the brick which resulted in an error instead it will simply be nil however were going off-topic here.

if I were to use workspace.hit.Parent instead of Instance:FindFirstChild() then it still wouldn’t work, I explained what I’m trying to understand in post #5 so you can go to check back on that.

1 Like

I don’t think Instance:FindFirstChild() work with instances.


When you do this

It print your character’s name probably because of the tostring() function.

1 Like

To find the player from the player’s character you should use:

game.Players:GetPlayerFromCharacter(character)

1 Like

I didn’t see that, you actually fixed the problem thank you, now it makes a lot of sense.

So the reason as to why it wasn’t working is because Instance:FindFirstChild()'s first parameter accepts a string and not an Instance so if we use

local plrCharacterbyWorkspace = workspace:FindFirstChild(tostring(hit.Parent))

Then it’s going to work, basically what we did there is that we got the reference of the Instance that we are trying to find then we get the string form of it by simply using the tostring() function which takes whatever you put into it and returns the string form of whatever you gave it and that way we can use Instance:FindFirstChild() safely.

It didn’t work for me before because I wasn’t using the tostring() function which is a very useful function.

What is the point of doing this?

local plrCharacter = hit.Parent
local plrCharacter2 = workspace:FindFirstChild(tostring(hit.Parent))

And why do you need to use tostring function when you can just do hit.Parent.Name ?

1 Like

Instance:FindFirstChild does not work with Instances.

You don’t need to do workspace:FindFirstChild(hit.Parent.Name) because hit.Parent will always exist, which is why the touched event was fired in the first place. Its redundant doing this.

You don’t need to do check if “hit.Parent” exists because if it didn’t exist the touched event wouldn’t even have fired.

That’s like doing hit.Parent.Parent:FindFirstChild(tostring(hit.Parent)) which makes absolutely 0 sense.

Plus if you are worried the part is not inside workspace, there is no point in worrying, Roblox characters are always located in workspace, and .Touched event works because of physics simulation, any parts that are outside workspace will not have their physics simulated thus the Touched event will never fire.

Still if you want to check you can just do if hit.Parent.Parent:IsA(“Workspace”) then, instead of
if workspace:FindFirstChild(tostring(hit.Parent)) then.