Obby Race Minigame

Hello, so my code isnt working and I dont really understand why.
What I’m trying to make is a Obby Race Minigame where your Depth is your points and the further you go down the more depth you get and once you get to 100 studs you earn some points

The issue is, the Depth isnt working and just kills the whole script when someone either joins and leaves or dies in the game

Here’s One of the Errors.

--// Game Serivces
local Lighting = game:GetService("Lighting")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

--// Define Vars
local GameModes = {"Classic"}
local GameMode = nil
local SpawnPointMinigames = workspace:WaitForChild("GameValues").SpawnArea
local GameValues = workspace:WaitForChild( 'GameValues' )
local MinigameHolder = GameValues:WaitForChild( 'Minigames' )
local GameStorage = ServerStorage:WaitForChild( 'GameStorage' )
local PlayerNeeds = GameStorage:WaitForChild( 'PlayerStuff' )
local Maps = GameStorage:WaitForChild( 'Minigames' )
local RemoteEvent = Instance.new( 'RemoteEvent', ReplicatedStorage )
local RemoteFunction = Instance.new( 'RemoteFunction', ReplicatedStorage )
--
local StartingPos = GameValues.SpawnArea.Start.CFrame
local MaxObbies = 10
local DesignType = 'Classic'
local EndArea = nil
--
local Cache = {}
local PlayersInGame = {}
local LobbyPlayers = {}
--
local Timer = 0
local Countdown = 4
local FallDamageHeight = 20
local Fix = false

--// Functions

function LevelManager(Data)
	if Data.LevelData.CurrentXP.Value >= Data.LevelData.NeededXP.Value then
		Data.LevelData.Level.Value = Data.LevelData.Level.Value + 1
		Data.LevelData.NeededXP.Value = Data.LevelData.NeededXP.Value * 1.5
		Data.LevelData.CurrentXP.Value = 0
		Data.Currencies.Coins.Value = Data.Currencies.Coins.Value + 400

		local Plr = game.Players:FindFirstChild(Data.Name)
		if Plr then
			RemoteEvent:FireClient({ 'Level', 'UpLvl', Plr })
		end
	end
end

function AddXP(PlrName, Amount)
	local Data = GetData(PlrName)
	local Mul = 1
	if Data then
		if Data.GamePasses.Premium.Value then
			Mul = 2
		end
		Data.LevelData.CurrentXP.Value = Data.LevelData.CurrentXP.Value + Amount * Mul
		LevelManager(Data)
	end
end

function SpawnCoins(Plate)
	for i = 1,4 do
		local Val = 100
		local Coin = ServerStorage.GameStorage.Extra.Coin:Clone()
		Coin.Parent = workspace:WaitForChild('GameValues').Currneyc.Coins
		Coin.CFrame = Plate.CFrame*CFrame.new(Random.new():NextInteger(-Plate.Size.X/2,Plate.Size.X/2),0,Random.new():NextInteger(-Plate.Size.Z/2,Plate.Size.Z/2))
		local x = Random.new():NextInteger(1,5)
		--[[if x == 5 then
			coin.BrickColor = BrickColor.new("Cyan")
			val = 4
		end]]

		game.Debris:AddItem(Coin,20)
		local conn
		
		conn = Coin.Touched:Connect(function(prt)
			if prt and prt.Parent == nil then return end
			local h = prt.Parent:FindFirstChild("Humanoid")
			if h then
				--// Add Data Stuff
				Coin:Destroy()
				conn:Disconnect()
			end
		end)
	end
end





function GetData(PlrName)

end

function DepthCounter()
	
end

function TopDepthUpdate(plr)
	
end

function MakePeopleInvisibleNear(Toggle)
	
end

function SetupRound()
	MinigameHolder:ClearAllChildren()
	PlayersInGame = {}
	LobbyPlayers = {}
		--[[
	local SpecialRoundOdds = math.random(1,100)
	if SpecialRoundOdds <= 10 then
		-- Special Round
		local SelectedMode = nil
		while true do
			local Mode = GameModes[math.random(1, #GameModes)]
			if Mode ~= GameModes[ 'Classic' ] then
				SelectedMode = Mode
				break
			end
		end
	else
		-- Classic Round
		GameMode = GameModes[1]
	end
	]]
	GameMode = GameModes[1]
	RemoteEvent:FireAllClients({ 'Intermission', 'Display', 'The Game Mode Is '..GameMode..'!', 3})
	wait(3)
	RemoteEvent:FireAllClients({ 'Intermission', 'Hide' })
	
	--// Generate Obbies
	local SpawnObby = ServerStorage.GameStorage.Minigames.SpawnStage.SpawnStage:Clone()
	SpawnObby.Parent = GameValues.Minigames
	RemoteEvent:FireAllClients({ 'Intermission', 'Display', 'Loading Map..',3 })
	wait(3)
	local Start = GameValues.Minigames:WaitForChild('SpawnStage').SpawnPart
	for i = 1,MaxObbies do
		local NewObby = ServerStorage.GameStorage.Minigames.Obbies:GetChildren()[math.random(#ServerStorage.GameStorage.Minigames.Obbies:GetChildren())]:Clone()
		NewObby.Parent = GameValues.Minigames
		NewObby:SetPrimaryPartCFrame(Start.CFrame)
		Start = NewObby.End
	end
	RemoteEvent:FireAllClients({ 'Intermission', 'Hide' })
end

function SpawnPlayers()
	if GameMode == 'Classic' then
		-- Get Players And Put Them Into Table
		local Players = game.Players:GetPlayers()
		for i,v in pairs(Players) do
			local Tag = Instance.new( 'BoolValue', v.Character )
			Tag.Name = 'Alive'
			Tag.Value = true
			table.insert(PlayersInGame, v)
		end
		
		-- Spawn Players
		local Spawn = SpawnPointMinigames.Start
		for i,v in pairs(PlayersInGame) do
			if v:IsA('Players') and v.Character and v.Character:FindFirstChild('HumanoidRootPart') and v.Character:FindFirstChild( 'Humanoid' ) and v.Character.Humanoid.Health > 0 then
				local UpperTorso = v.Character.HumanoidRootPart
				UpperTorso.CFrame = CFrame.new(Spawn.Position.X, Spawn.Position.Y + 3, Spawn.Position.Z)
				RemoteEvent:FireAllClients({ 'Camera Management', 'End', 'Specific Player', v })
				wait(0.25)
			end
		end
		repeat
			script.Parent.GiveSound:Play()
			Countdown = Countdown - 1
			RemoteEvent:FireAllClients({'Countdown', 'Display', Countdown})
			wait(1)
		until Countdown <= 1
		RemoteEvent:FireAllClients({'Countdown', 'Hide', Countdown})
		RemoteEvent:FireAllClients({ 'Intermission', 'Display', 'GOOD LUCK!', 3})
		wait(3)
		RemoteEvent:FireAllClients({ 'Intermission', 'Hide' })
	end
end

function BeforeRound(Toggle)
	RemoteEvent:FireAllClients({ 'Camera Management', 'Begin', 'Everyone', GameValues.ViewBrick.CameraOne })
	wait(1.5)
	if Toggle == 'Begin' then
	
	elseif Toggle == 'End' then
		
	end
end

function FallDamageCheck(player)
	local character = player.Character
	local humanoid = character:FindFirstChild("Humanoid")
	local rootPart = character:FindFirstChild("HumanoidRootPart")

	if humanoid and rootPart then
		local highestPart = rootPart.Position.y - character:GetExtentsSize().y / 2
		local fallHeight = highestPart - character.PrimaryPart.Position.y

		if fallHeight >= FallDamageHeight then
			local fallDamage = (fallHeight - FallDamageHeight) / 10
			humanoid:TakeDamage(fallDamage)
		end
	end
end

function CalculateDepth(player)
	local referencePoint = GameValues.SpawnArea.Start.Position
	local currentDepth = math.floor((player.Character.HumanoidRootPart.Position.Y - referencePoint.Y) / 5)
	return currentDepth
end

function LaunchRound()
	print(GameMode)
	local Winner = nil
	local highestDepth = 0

	if GameMode == 'Classic' then
		SpawnPlayers()
		local playerDepths = {}
		for _, player in ipairs(game.Players:GetPlayers()) do
			playerDepths[player] = 0
		end
		wait(1)
		local Timer = 60 * 2
		repeat
			Timer = Timer - 1
			RemoteEvent:FireAllClients({ 'Timer', 'Display', Timer })
			GameValues.Settings.Timer.Value = Timer
			wait(1)
			local PlayersAlive = false
			for _, v in pairs(PlayersInGame) do
				if v and v.Character and v.Character:FindFirstChild('Humanoid') and v.Character.Humanoid.Health > 0 and v.Character:FindFirstChild('Alive') then
					PlayersAlive = true
				end
			end
			for i, v in pairs(workspace.GameValues.Minigames:GetDescendants()) do
				if v.Name == "GlowPart" then
					v.Touched:Connect(function()
						v:FindFirstChild("PlatformSound"):Play()
					end)
				elseif v.Name == "SpinPart" then
					local Info = TweenInfo.new(
						15,
						Enum.EasingStyle.Sine,
						Enum.EasingDirection.Out,
						math.huge,
						false,
						0
					)
					local TweenService = game:GetService("TweenService")
					local Tween = TweenService:Create(v, Info, { CFrame = v.CFrame * CFrame.Angles(0, math.rad(90), 0) })
					Tween:Play()
				end
			end
			for i, v in pairs(game.Players:GetPlayers()) do
				FallDamageCheck(v)
				if v.Character and v.Character:FindFirstChild('Humanoid') and v.Character.Humanoid.Health <= 0 then
					-- Player is dead, reset their depth
					playerDepths[v] = 0
					RemoteEvent:FireClient(v, { "Depth", "Update", 0 })
				end
			end
			for player, depth in pairs(playerDepths) do
				if player.Character then
					local character = player.Character
					local humanoid = character and character:FindFirstChild("Humanoid")

					if humanoid then
						local currentDepth = character.PrimaryPart.Position.Z
						if currentDepth > depth then
							playerDepths[player] = currentDepth
							RemoteEvent:FireClient(player, { "Depth", "Update", currentDepth })
						end
					end
				end
			end

			--// Determine Winner Either Depth Or Who Ever Finishes First
		until Timer <= 0
		for player, depth in pairs(playerDepths) do
			if depth > highestDepth then
				highestDepth = depth
				Winner = player
			end
		end
	end

	RemoteEvent:FireAllClients({ 'Timer', 'Hide' })

	local players = game.Players:GetPlayers()

	for _, v in pairs(game.Players:GetPlayers()) do
		if v and v.Character and v.Character:FindFirstChild('Humanoid') and v.Character.Humanoid.Health > 0 and v.Character:FindFirstChild('Alive') then
			v:LoadCharacter()
		end
	end

	if Winner then
		RemoteEvent:FireAllClients({ "Intermission", "Display", Winner.Name .. " wins with a depth of " .. highestDepth .. " studs!", 5 })
	else
		RemoteEvent:FireAllClients({ "Intermission", "Display", "No winner this time!", 5 })
	end
	wait(5)
	Fix = true
end

--// Preset



--// RemoteEvent Manager
RemoteEvent.OnServerEvent:Connect(function(Player, Input)
	
end)

--// RemoteFunction Manager
RemoteFunction.OnServerInvoke = function(Player, Input)
	
end

--// Loop
while true do
	local PlayerCount = #game.Players:GetPlayers()
	if PlayerCount >= 1 then
		Timer = 30
		RemoteEvent:FireAllClients({ 'Intermission', 'Display', 'Intermission',30})
		repeat
			Timer = Timer -1
			GameValues.Settings.Timer.Value = Timer
			RemoteEvent:FireAllClients({ 'Timer', 'Display', Timer})
			wait(1)
		until Timer <= 0
		wait(1)
		RemoteEvent:FireAllClients({ 'Timer', 'Hide'})
		RemoteEvent:FireAllClients({ 'Intermission', 'Hide' })
		Timer = 50*4
		Fix = false
		SetupRound()
		LaunchRound()
		repeat wait() until Fix
	else
		--local coinD = GameValues.Currneyc.CoinSpawner
		--if coinD then
			--SpawnCoins(coinD)
		--end
		RemoteEvent:FireAllClients({ 'Intermission', 'Display', '2 Players Needed('..#game.Players:GetPlayers()..')!',5})
	end
	wait(5)
end
1 Like

That v:IsA("Players") should always be false. That code will never run.

However, the issue is that at the top of the fallDamageCheck function, after local character, put:

if not character then
return
end

and it should fix the problem.

Sorry, I couldnt get the other error on there for some reason but here’s the other error too.

Change the if humanoid then with if humanoid and character.PrimaryPart then