Model child of workspace not always able to find workspace ancestor

Hello,

I’m having this strange issue while trying to check if a model belongs to workspace class using FindFirstAncestorWhichIsA(“Workspace”) and a dictionary.

Here is the sequence of my code

  1. Local script finds model in workspace and fires to server this model

    remoteEvent:FireServer(model)

  2. Server script receives model ref and stores into dictionary like:

    playerModels[player] = model

  3. Then after a few frames when the player dies or disconnects if I try to check if the model ref from the server script dictionary belongs to workspace like

    return model:FindFirstAncestorWhichIsA("Workspace") ~= nil

I usually get false when the player dies, but I get true when the player disconnects while the parent of the model never changes.

Does anyone have any idea why this may happen?

Regards,
Nightcaller

When you say model, are you referring to the Player’s character model?
If so, you might be overcomplicating things.

You could just do something like

game.Players.PlayerAdded:Connect(function(playerThatJoinedGame)
    
    print(playerThatJoinedGame.Name..' has joined the game!')
    
    playerThatJoinedGame.CharacterAdded:Connect(function(SpawnedCharacter)
        
        print(SpawnedCharacter.Name..' has spawned in!')
        
        local Humanoid = SpawnedCharacter:WaitForChild('Humanoid')
        Humanoid.Died:connect(function()
            print(SpawnedCharacter.Name..' has died!')
        end)
        
    end)
    
end)

game.Players.PlayerRemoving:Connect(function(playerThatJoinedGame)
    
    print(playerThatJoinedGame.Name..' is leaving the game!')
    
end)


1 Like

Hey @dispeller, I’m not referring to the players character model. I’m just “locking” or keeping track of models when the player interacts with it. So the model location can be anywhere under workspace. But sometimes even in the players backpack which is why I check for workspace.

It might be a bad idea to give the client side the ability to tell the server what should be removed.
An exploiter could easily tell the server to track something that shouldn’t be removed, then leave the game.

Ahh yeah, I see the importance of that. I have security measures along the way to make sure that the client is not able to interact with something they shouldn’t be.

Here’s a wacky implementation of something that I think would solve your problem

don't use this, the other one is 2x as fast
function IsObjUnderWorkspace(obj)
  local directoryString = obj:GetFullName()
  local splitDirectoryString = string.split(directoryString,'.')
  if splitDirectoryString[1] == 'Workspace' then
    return true
  end
  return false
end

or something like

function IsObjUnderWorkspace(obj)
  
  if obj.Parent == workspace then
    return true
  elseif obj.Parent == nil then
    return false
  end
  
  return IsObjUnderWorkspace(obj.Parent)
end

I actually tested both functions

using tick()
function AIsObjUnderWorkspace(obj)
  local directoryString = obj:GetFullName()
  local splitDirectoryString = string.split(directoryString,'.')
  if splitDirectoryString[1] == 'Workspace' then
    return true
  end
  return false
end

function BIsObjUnderWorkspace(obj)
  
  if obj.Parent == workspace then
    return true
  elseif obj.Parent == nil then
    return false
  end
  
  return BIsObjUnderWorkspace(obj.Parent)
end

target = script.Obj.Value

now = tick()
print(AIsObjUnderWorkspace(target))
print('Function A:',tick()-now)

now = tick()
print(BIsObjUnderWorkspace(target))
print('Function B:',tick()-now)

The first function took 0.00060868263244629 ticks
The second one only took 0.00037217140197754 ticks

2 Likes

That is a neat way of checking if something is under workspace!

I found that the underlying issue was another system that I had was migrating things back and forth between the server storage and workspace when the player dies. :sweat_smile:

Initially I think this would have worked.

function IsObjUnderWorkspace(obj)
    return model:FindFirstAncestorWhichIsA("Workspace") ~= nil
end

But if your code seg performs better, I’m all for optimization. Thanks so much for the help.

1 Like