Here’s what I’ve come up with so far:
v1 (Basic and incomplete)
(I’m currently editing it to improve the logic and also handle respawns, so don’t use this directly yet.)
local players = game:GetService('Players')
players.CharacterAutoLoads = false
function setSpawnLocation(character:Model)
-- Modify for your spawning logic
local spawnLocation = workspace:FindFirstChildOfClass('SpawnLocation')
if spawnLocation then
character:MoveTo(spawnLocation.Position)
else
character:MoveTo(Vector3.zero)
end
end
players.PlayerAdded:Connect(function(player)
local _,character = pcall(function()
return players:CreateHumanoidModelFromUserId(player.UserId)
end)
if character then
character.Name = player.Name
player.Character = character
character.Parent = workspace
setSpawnLocation(character)
else
player:LoadCharacter()
end
end)
v2:
(May still need some further testing, but it now supports: Teams, randomized spawns, spawn rotation, and respawning behavior.)
local players = game:GetService('Players')
players.CharacterAutoLoads = false
local spawnerList = {}
spawnerList.Neutral = {}
spawnerList.Teams = {}
local teams = game:GetService('Teams')
local function getTeamFromSpawner(spawner:SpawnLocation):Team?
for _,team in teams:GetTeams()::{Team} do
if team.TeamColor == spawner.TeamColor then
return team
end
end
return nil
end
local function addSpawner(spawner:SpawnLocation)
if spawner:IsA('SpawnLocation') then
if not spawner.Neutral then
local team = getTeamFromSpawner(spawner)
if team then
local teamColor = team.TeamColor.Name
if not spawnerList.Teams[teamColor] then
spawnerList.Teams[teamColor] = {}
end
table.insert(spawnerList.Teams[teamColor],spawner)
return
end
end
table.insert(spawnerList.Neutral,spawner)
end
end
workspace.DescendantAdded:Connect(function(spawner:SpawnLocation)
addSpawner(spawner)
end)
for _,spawner:SpawnLocation in workspace:GetDescendants() do
addSpawner(spawner)
end
workspace.DescendantRemoving:Connect(function(spawner:SpawnLocation)
if spawner:IsA('SpawnLocation') then
local team = getTeamFromSpawner(spawner)
if team then
local teamColor = team.TeamColor.Name
local indexTeam = table.find(spawnerList.Teams[teamColor],spawner)
if indexTeam then
table.remove(spawnerList.Teams[teamColor],indexTeam)
end
if #spawnerList.Teams[teamColor] == 0 then
spawnerList.Teams[teamColor] = nil
end
else
local indexNeutral = table.find(spawnerList.Neutral,spawner)
if indexNeutral then
table.remove(spawnerList.Neutral,indexNeutral)
end
end
end
end)
local function setSpawnLocation(player:Player,character:Model)
-- Modify for your spawning logic
local function moveToSpawner(spawner:SpawnLocation)
character:MoveTo(spawner.Position)
local humanoidRootPart = character:WaitForChild('HumanoidRootPart')::Part
task.wait()
humanoidRootPart.CFrame = CFrame.new(humanoidRootPart.Position)*CFrame.Angles(0,math.rad(spawner.Orientation.Y),0)
end
local playerTeam = player.Team
if playerTeam then
local teamTable = spawnerList.Teams[playerTeam.TeamColor.Name]
if teamTable then
local teamTableCount = #teamTable
if teamTableCount > 0 then
local randomizedSpawner = teamTable[math.random(1,teamTableCount)]
moveToSpawner(randomizedSpawner)
return
end
end
end
local neutralCount = #spawnerList.Neutral
if neutralCount > 0 then
local randomizedSpawner = spawnerList.Neutral[math.random(1,neutralCount)]
moveToSpawner(randomizedSpawner)
return
end
character:MoveTo(Vector3.zero)
end
local function forceRespawn(player:Player)
local _,character = pcall(function()
return players:CreateHumanoidModelFromUserId(player.UserId)
end)
if character then
local humanoid = character:WaitForChild('Humanoid')::Humanoid
local diedEvent,removingEvent
local function eventFunction()
diedEvent:Disconnect()
removingEvent:Disconnect()
task.wait(players.RespawnTime)
forceRespawn(player)
end
diedEvent = humanoid.Died:Connect(eventFunction)
removingEvent = character:GetPropertyChangedSignal('Parent'):Connect(function()
if not character.Parent then
eventFunction()
end
end)
character.Name = player.Name
player.Character = character
character.Parent = workspace
setSpawnLocation(player,character)
else
player:LoadCharacter()
end
end
players.PlayerAdded:Connect(function(player)
forceRespawn(player)
end)
I don’t like that I have to write my own custom spawning logic, but perhaps there’s a better method. This may also fail to trigger certain events, though CharacterAdded still seems to work.
Definitely test before using in a live server, obviously. I’ve tested this exclusively in Studio. However, this was not tested in an environment where R15 is set as the only rig type allowed, so I’m not sure if that will alter this or not.
I’ve now tested in a live server with the rig type exclusive to one or the other. This script appears to work, allowing me to join with R6 or R15 and having either one appear, regardless of the game settings.