The Galatic Speedway in Roblox Studio Doesn't Seem to Work Anymore (Can we fix it?)

Some of the Roblox Studio education is within their pre-loaded project called Galatic Speedway.

I wanted to give the speeder physics a try but it looks like there is now a bug that doesn’t allow the player to fly with the default tester speeder (or any speeder you build, for that matter).

It now gives an error when you try to spawn/fly the speeder:

Player:Move called, but player currently has no humanoid.

I am wondering if the script is converting or despawning the player after it turns the player into a speeder? And this is causing the error? I had no idea.

I believe the problem is in ReplicatedStorage > ModuleScripts > PlayerConverter but I am not 100% certain. If you want you can fire up Studio and check it out.

If anyone can figure out the solution and post it here, maybe the Roblox team can patch and we can get this resource working for new players like myself again! :slight_smile:

PlayerConverter script shown below.

-- ================================================================================
-- ================================================================================
-- PlayerConverter
-- ================================================================================
-- ================================================================================

local PlayerConverter = {}

-- ================================================================================
-- VARIABLES
-- ================================================================================
-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local PhysicsService = game:GetService("PhysicsService")
local ContextActionService = game:GetService("ContextActionService")
local GuiService = game:GetService("GuiService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

-- Device check
local IS_CONSOLE = GuiService:IsTenFootInterface()
local IS_MOBILE = UserInputService.TouchEnabled and not UserInputService.MouseEnabled and not IS_CONSOLE

-- SpeederScripts
local SpeederScripts = ReplicatedStorage:FindFirstChild("SpeederScripts")
local Controller = SpeederScripts:FindFirstChild("Controller")

-- Events
local Events = ReplicatedStorage:FindFirstChild("Events")
local LoadSpeeder = Events:FindFirstChild("LoadSpeeder")
local LoadCharacter = Events:FindFirstChild("LoadCharacter")
local RemoveActivePlayer = Events:FindFirstChild("RemoveActivePlayer")
local CheckpointEvent = Events:FindFirstChild("CheckpointEvent")

-- Sounds
local Soundscape = game.Soundscape
local ExitSound = Soundscape:FindFirstChild("ExitSound")

-- SpeederSpawnLocation part
local SpeederSpawnLocation = workspace:FindFirstChild("SpeederSpawnLocation")

-- Static variables
local _SPEEDEROBJECTSCOLLISIONGROUP = "SpeederObjects"
-- ================================================================================


-- ================================================================================
-- LOCAL FUNCTIONS
-- ================================================================================
local function setModelAnchored(parent, anchored)
	for _, child in ipairs(parent:GetChildren()) do
		if (child:IsA("BasePart")) or (child:IsA("MeshPart")) then
			child.Anchored = anchored
		end
		setModelAnchored(child, anchored)
	end
end -- setModelAnchored()

local function setModelCanCollide(parent, canCollide)
	for _, child in ipairs(parent:GetChildren()) do
		if (child:IsA("BasePart")) or (child:IsA("MeshPart")) then
			child.CanCollide = canCollide
		end
		setModelAnchored(child, canCollide)
	end
end -- setModelCanCollide()

local function setModelTransparency(parent, transparency)
	for _, child in ipairs(parent:GetChildren()) do
		if (child:IsA("BasePart")) or (child:IsA("MeshPart")) then
			child.Transparency = transparency
		end
		setModelTransparency(child, transparency)
	end
end -- setModelTransparency()

local function removeLimbsAndThings(character)
	for _, child in ipairs(character:GetChildren()) do
		removeLimbsAndThings(child)
		if (not child:IsA("Humanoid")) and (not child:IsA("Motor6D")) 
			and (child.Name ~= "Head") and (child.Name ~= "UpperTorso") then
				child:Destroy()
		end
	end
end -- removeLimbsAndThings()

local function insertModelIntoCharacter(character, model)
	for _, child in ipairs(model:GetChildren()) do
		child.Parent = character
		insertModelIntoCharacter(child, child)
	end
end -- insertModelIntoCharacter()

local function setCollisionGroup(parent, group)
	for _,part in pairs(parent:GetChildren()) do
		if (part:IsA("BasePart") or (part:IsA("MeshPart"))) then
			PhysicsService:SetPartCollisionGroup(part, group)
		end
	end
end -- SetCollisionGroup()
-- ================================================================================

-- ================================================================================
-- PUBLIC FUNCTIONS
-- ================================================================================
function PlayerConverter:PlayerToSpeeder(selection, racing)
	if racing == nil then racing = false end
	
	-- Fire RemoteEvent to handle conversion server-side
	LoadSpeeder:FireServer(selection, racing)
end -- PlayerConverter:PlayerToSpeeder()

function PlayerConverter:PlayerToSpeederClient(racing)
	if racing == nil then racing = false end
	 
	local Players = game:GetService("Players")
	local player = Players.LocalPlayer
	local PlayerGui = player:FindFirstChild("PlayerGui")
	
	-- Get player's character
	local character = player.Character or player.CharacterAdded():wait()
	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	local head = character:FindFirstChild("Head")
	
	-- Move HumanoidRotPart out of range of interaction NPC
	if humanoidRootPart then
		humanoidRootPart.Position = humanoidRootPart.Position + Vector3.new(0, 40, 0)
		print("Move HumanoidRotPart out of range of interaction NPC")
	end
	if head then
		head.Position = head.Position + Vector3.new(0, 40, 0)
	end
		
	-- Lock/Center and hide mouse
	UserInputService.MouseIconEnabled = false
	UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	UserInputService.MouseIconEnabled = false
	
	-- Disable touch control GUIs on mobile devices
	if IS_MOBILE then
		local TouchGui = PlayerGui:WaitForChild("TouchGui")
		TouchGui.Enabled = false
	end
	
	if racing then
		local countdownGui = PlayerGui:WaitForChild("CountdownGui")
		countdownGui.TimerFrame.Visible = false
	end
end -- PlayerConverter:PlayerToSpeederClient()

function PlayerConverter:PlayerToSpeederServer(player, selection, racing)
	if racing == nil then racing = false end
	
	-- Get player's character
	local character = player.Character or player.CharacterAdded:wait()
	
	-- Anchor and make limbs transparent
	setModelAnchored(character, true)
	setModelCanCollide(character, false)
	setModelTransparency(character, 1)
	
	-- Remove limbs and unecessay character parts
	removeLimbsAndThings(character)
	
	-- Clone selected speeder
	local speeder = selection:clone()
	print ("Speeder cloned")
	
	-- Set character's PrimaryPart to speeder's PrimaryPart
	local body = speeder:FindFirstChild("Body")
	assert(body, "All speeders must have a part named Body. It will be used as the PrimaryPart")
	speeder.PrimaryPart = body
	character.PrimaryPart = body
	character.PrimaryPart.Name = "HumanoidRootPart"
	
	-- Set collision group so that players cannot collide when they are speeders
	setCollisionGroup(speeder, _SPEEDEROBJECTSCOLLISIONGROUP)
	
	-- Unanchor speeder
	setModelAnchored(speeder, false)
	
	-- Insert speeder model into character
	insertModelIntoCharacter(character,speeder)
	
	-- Clone speeder scripts into player
	local controller = Controller:clone()
	controller.Parent = character
	
	-- Move player to SpeederSpawnLocation
	character:SetPrimaryPartCFrame(SpeederSpawnLocation.CFrame)
	
	LoadSpeeder:FireClient(player, racing)
end -- PlayerConverter:PlayerToSpeederServer()

-- Must be called client-side
function PlayerConverter:SpeederToPlayer(playSound)
	-- LoadCharacter has to be fired server-side, so fire a RemoteEvent
	-- to get it there
	LoadCharacter:FireServer()
	PlayerConverter:SpeederToPlayerClient(playSound)
end -- PlayerConverter:SpeederToPlayer()

function PlayerConverter:SpeederToPlayerServer(player)
	player:LoadCharacter()
	
	LoadCharacter:FireClient(player)
end -- PlayerConverter:SpeederToPlayer()

function PlayerConverter:SpeederToPlayerClient(playSound)
	if playSound == nil then playSound = true end
	
	-- Play sounds
	if playSound and (UserInputService.MouseBehavior ~= Enum.MouseBehavior.Default) then
		ExitSound:Play()
	end
	
	-- Unlock and show mouse
	UserInputService.MouseBehavior = Enum.MouseBehavior.Default
	UserInputService.MouseIconEnabled = true
	
	-- Remove user from race ActivePlayer's list (if racing)
	RemoveActivePlayer:FireServer()
	
	-- Enable touch control GUIs on mobile devices
	local Players = game:GetService("Players")
	local player = Players.LocalPlayer
	local PlayerGui = player:FindFirstChild("PlayerGui")
	if IS_MOBILE then
		local TouchGui = PlayerGui:WaitForChild("TouchGui")
		
		TouchGui.Enabled = true
	end	
	
	local TopBar = PlayerGui:WaitForChild("TopBar")
	TopBar.Enabled = false	
end -- PlayerConverter:SpeederToPlayerClient()

function PlayerConverter:UnlockPlayerControls()
	UserInputService.MouseBehavior = Enum.MouseBehavior.Default
	UserInputService.MouseIconEnabled = true
	
	-- Remove user from race ActivePlayer's list (if racing)
	RemoveActivePlayer:FireServer()
	
	-- Enable touch control GUIs on mobile devices
	local Players = game:GetService("Players")
	local player = Players.LocalPlayer
	local PlayerGui = player:FindFirstChild("PlayerGui")
	if (IS_MOBILE) then
		local TouchGui = PlayerGui:WaitForChild("TouchGui")
		
		TouchGui.Enabled = true
	end	
	
	local TopBar = PlayerGui:WaitForChild("TopBar")
	TopBar.Enabled = false
end -- PlayerConverter:UnlockPlayerControls()
-- ================================================================================


return PlayerConverter

I did a lot of digging. To me it looks like the character:Destroy() in game.ReplicatedStorage.SpeederScripts.Controller and character:Destroy() in game.ReplicatedStorage.SpeederScripts.PilotSeat is a little bit of the culprit here, as commenting them out gets you further until the countdown stops, but then it fails again. I also commented out every line with the word “Explode” in it, which got rid of most of the lag. From my testing, race still works, but free roam doesn’t. The place for these edits is attached if you want to look at it.

Have a nice day,
Grayseon

GalacticSpeedway.rbxl (1.9 MB)

1 Like