Not spawning near other players

Hello everyone! I am trying to make a fighting game. A map is randomly chosen, and all players teleport to that map. The spawn locations of the selected map will enable, while all others disable. But there’s a problem…

I don’t really want players spawning on top of eachother for obvious reasons. How can I disable a spawn location when a player is near it or spawning on it? And how can I enable it again when a player is far away? I can’t simply re-enable it when a player is far because players would end up spawning in the wrong map.

I think that the best way to do this would be to calculate the magnitude of the player to the spawnlocation, but there are issues with this as mentioned above.

Any help with this would be much appreciated! :slight_smile:

(Also I never really considered if two players spawned on the same spawnlocation at the exact same time, but I’m just going to assume that isn’t an issue.)

If you have all the spawn locations in one location, you could potentionally do something like this:

local Locations = game.Workspace.Map1.SpawnLocations
local ClosestAllowed = 30 -- i.e. all players must be at least 30 studs away
game.Players.PlayerAdded:Connect(function(plr)
    plr.CharacterAdded:Connect(function(char)
        while true do
            local Spawn = Locations:GetChildren()[math.random(#Locations:GetChildren())
            local Pos = Spawn.Position

            for _, p in ipairs(game.Players:GetPlayers()) do
                if p.Character then
                    local Distance = (p.Character.HumanoidRootPart.Position - Pos).Magnitude
                    if Distance < ClosestAllowed then
                        continue
                    else
                        char:MoveTo(pos)
                        break
                    end
               end
           end
        end
    end)
end)

Have an actual spawn location located somewhere off the map that the players will spawn at initially. They will only be there for a fraction of a second, but still good to have them spawn seperately.

This code is untested, and the logic should be correct, however it does have a few limitations. You will need to ensure that there are sufficient spawn points, such that at least one spawn point will always be ClosestAllowed studs away from the nearest player.

This is just one example of the implementation. There may be other solutions, however this is the one I came up with.

Yeah, there’s a spawnlocation in the lobby. I might just end up placing invisible parts all over the map, making an enabled and disabled feature by changing the colour of the part or something and using your script for the rest. I’ll let you know if it works or not

Wait actually I don’t think that what I’m doing would work with this because I have different spawn locations for different maps and they are all spread out among the map. Btw I suck at scripting if it wasn’t already obv

maybe letting players spawn on eachother isn’t the worst option bc they’re immortal until they move just kinda inconvenient imo

I don’t recommed using SpawnLocations in this game.
You could get the span of the map (How the wide the map is X and Y),
pick a random X and Y (Get X and Y magnitude of every player such that it picks a different value if its near anyone)
and Raycast to find the Y value.

local MapSizeX = 1000 --Change to map size in X
local MapSizeY = 100 --Change to map size in Y
local MapSizeZ = 1000 --Change to map size in Z
local MapPositionX = 0 --Get the center position of the map in X
local MapPositionY = 0 --Get the center position of the map in Y
local MapPositionZ = 0 --Get the center position of the map in Z
local Separation = 50 --How far the player must be away from others
local Random = Random.new()

function GenerateSpawn()
	local Participants = game.Players:GetPlayers() --An array, change to participating players if needed
	local RandomPoint = {Random:NextNumber(0, MapSizeX) - MapSizeX / 2 + MapPositionX, Random:NextNumber(0, MapSizeZ) - MapSizeZ / 2 + MapPositionZ}
	for _, Player in pairs(Participants) do
		local Character = Player.Character
		local HumanoidRootPart = Character.HumanoidRootPart
		local Magnitude = math.sqrt((HumanoidRootPart.Position.X - RandomPoint[1]) ^ 2, (HumanoidRootPart.Position.Z - RandomPoint[2]) ^ 2)
		if Magnitude < Separation then
			return GenerateSpawn()
		end
	end
	local Result = workspace:Raycast(Vector3.new(RandomPoint[1], MapPositionY + MapSizeY / 2, RandomPoint[2]), Vector3.new(0, -MapSizeY, 0))
	if Result then
		local Y = Result.Position.Y
		return Vector3.new(RandomPoint[1], Y + 2.5, RandomPoint[2])
	else
		return GenerateSpawn()
	end
end

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Character)
		local Spawn = GenerateSpawn()
		Character:PivotTo(CFrame.new(Spawn))
	end)
end)

In hindsight you probably could’ve used :MoveTo instead of having to Raycast, but I believe this is fine as well