Spawnpoint is not a valid member of Workspace "Workspace"

I’m making a team system for a game I’m making for me and my friends, but for some reason every time I try to playtest it returns this error.


Here’s the relevant script:

teams = game.Teams
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")

[player ids redacted for privacy]
-- Blue hive

[player ids redacted for privacy]
-- Red hive

blueHive = {[player ids redacted for privacy]}
redHive = {[player ids redacted for privacy]}
-- Hives as lists

for i, v in ipairs(blueHive) do
	print(v)
	if v == plr.UserId then
		print("blue")
		plr.Team = teams["Blue Hive"]
		char:PivotTo(game.Workspace.BlueSpawn.Part.CFrame)
		break
	end
end
for i, v in ipairs(redHive) do
	print(v)
	if v == plr.UserId then
		print("red")
		plr.Team = teams["Red Hive"]
		char:PivotTo(game.Workspace.RedSpawn.Part.CFrame)
		break
	end
end

When I replace Workspace with Workspace it works the first time I run it and then breaks again.
Here’s my workspace:
image
What is going on?

It is likely that the script searches for it as soon as it runs, but it can still run even if the entire game isn’t loaded yet. You should probably add a task.wait(1) first.

whenever u write a local script, u gotta wait for the assets to load because server → client has latency, so you do:

local blueThing = workspace:WaitForChild("blueThing")
1 Like

This works, but there’s a weird awkward moment of the player being in the middle of nowhere before it happens. Is there a way I can have it stop the player from loading until the spawnpoint has also loaded?

This is a better solution, but still has the issue I described

you can disable character auto loading in Players and create a loading screen where you load all game assets in then tell the server when thats done who then loads the character

1 Like

try this ( replace the redacted ids with the actual ones ofc)
and some advice, don’t do game.Workspace, just do workspace; and try and use variables more often because it disencourages repeated code and really does help in the long run.

local teams = game:GetService("Teams")
local players = game:GetService("Players")
local plr = players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")
local humanoidRootPart = char:WaitForChild("HumanoidRootPart")

local blueSpawn = workspace:WaitForChild("BlueSpawn")
local redSpawn = workspace:WaitForChild("RedSpawn")

[player ids redacted for privacy]
-- Blue hive

[player ids redacted for privacy]
-- Red hive

blueHive = {[player ids redacted for privacy]}
redHive = {[player ids redacted for privacy]}
-- Hives as lists

task.defer(function()
	for i, v in ipairs(blueHive) do
		print(v)
		if v == plr.UserId then
			print("blue")
			plr.Team = teams["Blue Hive"]
			humanoidRootPart.CFrame = blueSpawn.Part.CFrame
		end
	end
end)

task.defer(function()
	for i, v in ipairs(redHive) do
		print(v)
		if v == plr.UserId then
			print("red")
			plr.Team = teams["Red Hive"]
			humanoidRootPart.CFrame = redSpawn.Part.CFrame
		end
	end
end)

i see, but im glad the original problem is fixed lol

i noticed that ur storing ur player ids in a localscript, which is a vulnerability because exploiters can see with an injected script editor

this isnt the solution to ur second problem with the characters, but it would be a good idea to use networking (remote function) to invoke the server if the player is valid for the team change

another thing, ur localscript is changing a player’s team and moving them to a location, which can cause network ownership / replication issues. u can safely do this on the server-side, so that the team change and character movement is validated / replicated across all players

:slight_smile:

actually after looking back at the code i just realised something really important
you cannot change the players team via a localscript, that is all strictly client sided and you should really be handling all this stuff on the server, and teleporting the player (& changing the team) with character added

Just 2 questions about this, 1. How do I load the player once everything is ready? plr:LoadCharacter doesn’t seem to do anything.
2. The reference page doesn’t really make sense so could you explain what task.defer does?

So should I just copy-paste everything into a server script then?

So should I just copy-paste everything into a server script then?

yeah of course.
plr:LoadCharacter only works on a server script so it won’t work on this local script.
task.defer basically just lets the block of code run in its own bubble which means it dosent hold up the script and wait until the for loop is done looping.

So should I just copy-paste everything into a server script then?

yes and no, to get the player you can’t use localplayer so you’d have to use another way. I’ll send you the server script in a second

make a new server script and place it into ServerScriptService, and change this script below to work with your tables (for the hives)

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

local blueSpawn = workspace:WaitForChild("BlueSpawn")
local redSpawn = workspace:WaitForChild("RedSpawn")

--[player ids redacted for privacy]
-- Blue hive

--[player ids redacted for privacy]
-- Red hive

local blueHive = {}
local redHive = {}
-- Hives as lists

Players.PlayerAdded:Connect(function(Player)
	local Character = Player.CharacterAdded:Wait()
	local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
	
	if table.find(blueHive, Player.UserId) then
		Player.Team = Teams["Blue Hive"]
		HumanoidRootPart.CFrame = blueSpawn
	elseif table.find(redHive, Player.UserId) then
		Player.Team = Teams["Red Hive"]
		HumanoidRootPart.CFrame = redSpawn
	end
end)
1 Like

I tried running the script with CharacterAutoLoads on and task.defer() used the way you suggested and nothing seems to happen.

yeh essentially, u move it to server script service but u will have to make some changes.

u will have to connect the Players.PlayerAdded event and pass the player to a function that handles ur team change and teleport

local Players = game:GetService("Players")

local function setTeam(player: Player)
    if table.find(redHive, player.UserId) then
         -- team change + move player.Character
    end

    -- do the same thing for the other team
end

Players.PlayerAdded:Connect(setTeam)

this is a common way to do this

This is because FilteringEnabled is enabled by default.

I updated my code because it wasn’t that good and im tired but this should work without problem hopefully

Just re-enable CharacterAutoLoads, you don’t have to worry about that

The spawnpoint loads to the server before the player could load. Tweaking the wait time a bit(eg. 0.1, 0.5) could likely fix it.

Also, you can use :WaitForChild(instance) so that it will wait until it loaded.