How to optimize this vehicle clean-up script?

I have a script that works like this. A player hops in a car, does whatever, but script only activates when the player hops out of the car. The script then sends a RobloxNotification to the player, saying his or her car will despawn within 2-3 minutes if the player (or another player) doesn’t re-claim it. Works pretty well, except for a few issues:

  1. Each time a player hops out of the car, I call a task.spawn() function to begin the countdown independently of the rest of the code. I’d imagine this could cause issues if a player is constantly hopping in and out of the car.
  2. There is an issue where if a player hops out of the car but immediately hops back in, the countdown will not stop. So basically, if a player were to hop out of the car and then back in, the countdown would continue. If the player hopped out of the car again around the three minute mark, the car would despawn in like 2 seconds instead of waiting the normal 3 minutes/180 seconds.

I’m looking for ways to optimize this script and make it so that the countdown stops whenever the car is reclaimed. Here is my script:

local actualVehicle = script.Parent
local seat = actualVehicle.Seat
local proxPrompt = seat.PromptLocation.EndorsedVehicleProximityPromptV1_
local lastDriver = nil

proxPrompt.Triggered:Connect(function(who)
	seat:Sit(who.Character.Humanoid)
	proxPrompt.Enabled = false
end)

seat:GetPropertyChangedSignal("Occupant"):connect(function()
	if seat.Occupant ~= nil then
		local Humanoid =seat.Occupant
		local Char = Humanoid and Humanoid.Parent
		local Player = Char and game.Players:GetPlayerFromCharacter(Char)
		if Player then
			lastDriver = Player
			seat:SetNetworkOwner(Player)
			actualVehicle.Parent = Char
			Humanoid.Died:Connect(function()
				if Player == lastDriver then
					game.Debris:AddItem(actualVehicle,2)
				end
			end)
		end	
	else
		proxPrompt.Enabled = true
		actualVehicle.Parent = workspace
		seat:SetNetworkOwnershipAuto()
		task.spawn(function()
			--- despawn the plane if no one comes back to get it
			local despawnTime = actualVehicle:GetAttribute("despawnTime")
			if despawnTime == nil then
				despawnTime = 60
			end
			game.ReplicatedStorage.Remotes.notificationSystem:FireClient(lastDriver,"Vehicle Notification","Your vehicle will despawn in "..despawnTime.." seconds if left unattended.")
			task.wait(despawnTime)
			if seat.Occupant == nil then
				actualVehicle:Destroy()
			end
		end)
	end
end)

Is there a way I could despawn the function seen towards the end?

task.spawn(function()
			--- despawn the plane if no one comes back to get it
			local despawnTime = actualVehicle:GetAttribute("despawnTime")
			if despawnTime == nil then
				despawnTime = 60
			end
			game.ReplicatedStorage.Remotes.notificationSystem:FireClient(lastDriver,"Vehicle Notification","Your vehicle will despawn in "..despawnTime.." seconds if left unattended.")
			task.wait(despawnTime)
			if seat.Occupant == nil then
				actualVehicle:Destroy()
			end
		end)

The above snippet of code is the problematic line(s), I’d imagine

You could look up coroutines or,
Connect an event to the seat so when someone sits in it they reset the despawnTime attribute, then check for that before destroying it or,
Use a named function when spawning the task, which would allow you to use task.cancel() to stop it.

1 Like

Could you give me an example of spawning a named function, and then using task.cancel to stop it? I have played around with it before and it only seemed to work when using task.delay. If the there was no “task” running beforehand and I tried cancelling it, it would usually error out the code.

What I was gonna do was do something like this:

local actualVehicle = script.Parent
local seat = actualVehicle.Seat
local proxPrompt = seat.PromptLocation.EndorsedVehicleProximityPromptV1_
local lastDriver = nil

proxPrompt.Triggered:Connect(function(who)
	seat:Sit(who.Character.Humanoid)
	proxPrompt.Enabled = false
end)

local despawner = function()
      task.wait(180)
      actualVehicle:Destroy()
end)

seat:GetPropertyChangedSignal("Occupant"):connect(function()
	if seat.Occupant ~= nil then
		local Humanoid =seat.Occupant
		local Char = Humanoid and Humanoid.Parent
		local Player = Char and game.Players:GetPlayerFromCharacter(Char)
		if Player then
                        task.cancel(despawner)
			lastDriver = Player
			seat:SetNetworkOwner(Player)
			actualVehicle.Parent = Char
			Humanoid.Died:Connect(function()
				if Player == lastDriver then
					game.Debris:AddItem(actualVehicle,2)
				end
			end)
		end	
	else
		proxPrompt.Enabled = true
		actualVehicle.Parent = workspace
		seat:SetNetworkOwnershipAuto()
		task.spawn(despawner)
	end
end)

Ok, so I tried this script:

local actualVehicle = script.Parent
local seat = actualVehicle.Seat
local proxPrompt = seat.PromptLocation.EndorsedVehicleProximityPromptV1_
local lastDriver = nil
local despawnMode = false

local despawnTime = actualVehicle:GetAttribute("despawnTime")
if despawnTime == nil then
	despawnTime = 60
end

proxPrompt.Triggered:Connect(function(who)
	seat:Sit(who.Character.Humanoid)
	proxPrompt.Enabled = false
end)

local despawner = (function()
	despawnMode = true
	task.wait(despawnTime)
	if seat.Occupant == nil then
		actualVehicle:Destroy()
	end
end)

seat:GetPropertyChangedSignal("Occupant"):connect(function()
	if seat.Occupant ~= nil then
		local Humanoid =seat.Occupant
		local Char = Humanoid and Humanoid.Parent
		local Player = Char and game.Players:GetPlayerFromCharacter(Char)
		if Player then
			if despawnMode == true then
				task.cancel(despawner)
				despawnMode = false
			end
			lastDriver = Player
			seat:SetNetworkOwner(Player)
			actualVehicle.Parent = Char
			Humanoid.Died:Connect(function()
				if Player == lastDriver then
					game.Debris:AddItem(actualVehicle,2)
				end
			end)
		end	
	else
		proxPrompt.Enabled = true
		actualVehicle.Parent = workspace
		seat:SetNetworkOwnershipAuto()
		game.ReplicatedStorage.Remotes.notificationSystem:FireClient(lastDriver,"Vehicle Notification","Your vehicle will despawn in "..despawnTime.." seconds if left unattended.")
		task.spawn(despawner)
	end
end)

Basically, any time the player leaves, it is supposed to spawn that “despawner” function, which it does. However, when I go back into my vehicle, I get this error:
“:38: invalid argument #1 to ‘cancel’ (thread expected, got function)”

How do I fix this?

local despawner = task.spawn(function()
Also you may need to check it’s running before cancelling.