Implement despawn

I have tried multiple different methods but none have worked correctly.
How would I implement a system that uses breakCart() if the cart has not been sat in within 20 seconds, and if a player does not jump back into the cart after 15 seconds?

--!strict
local Players = game:GetService("Players")

local SoundEffects = require(script:WaitForChild("SoundEffects"))
local ParticleEffects = require(script:WaitForChild("ParticleEffects"))
local getStatus = require(script:WaitForChild("getStatus"))
local breakCart = require(script:WaitForChild("breakCart"))
local setupCollisionGroups = require(script:WaitForChild("setupCollisionGroups"))
local Coupling = require(script:WaitForChild("Coupling"))

local Cart = script.Parent
local Throttle = script:WaitForChild("Throttle")
local Base = Cart:WaitForChild("Base")
local Motors = Base:WaitForChild("Motors"):GetChildren()
local Seat = Cart:WaitForChild("Seat") :: Seat

local Buttons = Cart:WaitForChild("Buttons")

local CurrentPlayer: Player? = nil

-- They may not be set up already
setupCollisionGroups()

local function occupantIsPlayer(player: Player): boolean
	local occupant = Seat.Occupant
	if occupant then
		return occupant.Parent == player.Character
	end
	return false
end

script.SetThrottle.OnServerEvent:Connect(function(player: Player, throttle)	
	if occupantIsPlayer(player) and type(throttle) == 'number' then
		Throttle.Value = math.clamp(throttle, -1.0, 1.0)
	end
end)

Buttons:WaitForChild("Stop"):WaitForChild("ClickDetector").MouseClick:Connect(function(player)
	Throttle.Value = 0
end)
Buttons:WaitForChild("Start"):WaitForChild("ClickDetector").MouseClick:Connect(function(player)
	if Throttle.Value == 0 then
		Throttle.Value = 0.8
	elseif math.abs(Throttle.Value) <= 0.2 then
		Throttle.Value = math.sign(Throttle.Value) * 0.8
	end
end)
Buttons:WaitForChild("Decouple"):WaitForChild("ClickDetector").MouseClick:Connect(function(player)
	Coupling.decouple()
end)

local LocalCartUI = script:WaitForChild("LocalCartUI")
function setup(player: Player)
	local playerGui = player:FindFirstChild("PlayerGui") :: PlayerGui
	if not playerGui:FindFirstChild("LocalCartUI") then
		local localScript = LocalCartUI:Clone()
		localScript.Disabled = false
		localScript.Parent = playerGui
	end
end

function teardown(player: Player)
	
end

Seat:GetPropertyChangedSignal("Occupant"):Connect(function()
	if CurrentPlayer then
		teardown(CurrentPlayer)
	end
	CurrentPlayer = nil
	local currentOccupant = Seat.Occupant
	if currentOccupant then
		CurrentPlayer = Players:GetPlayerFromCharacter(currentOccupant.Parent)
	end
	if CurrentPlayer then
		setup(CurrentPlayer)
	end
end)

local function slowDownIfNoOccupant(dt)
	-- Slow down if nobody is riding
	if not Seat.Occupant then
		local decay = 0.01 * dt
		if math.abs(Throttle.Value) < decay then
			Throttle.Value = 0
		else
			Throttle.Value -= math.sign(Throttle.Value) * decay
		end
	end
end

local lastPosition = Base.Position
local iteration = math.random(1, 100)
while true do
	local dt = task.wait()
	
	local shouldPlaySounds = script:GetAttribute("PlaySounds")
	
	-- Only do the raycasts every 4th frame
	iteration += 1
	if iteration % 4 == 0 then
		local isOnTrack, expired = getStatus(script:GetAttribute("DespawnAfter"))
		if not isOnTrack and shouldPlaySounds then
			SoundEffects.stopSounds()
		end
		if expired then
			breakCart()
			break
		end
	end
	
	local thisPosition = Base.Position
	SoundEffects.movedBy((lastPosition - thisPosition).Magnitude)
	lastPosition = thisPosition
	
	local velocity = Base.AssemblyLinearVelocity.Magnitude
	
	local screeching = ParticleEffects.updateSparks(velocity)
	
	if shouldPlaySounds then
		SoundEffects.playSounds(dt, velocity, screeching)
	end
		
	slowDownIfNoOccupant(dt)
	
	-- Apply the calculated throttle
	for _, motor in ipairs(Motors) do
		motor.AngularVelocity = -script:GetAttribute("MaxSpeed") * Throttle.Value
		motor.MotorMaxTorque = 10000 * math.abs(Throttle.Value)^2
	end
end
1 Like

You are trying to create a deepen system? If yes then simply use Destroy()

The cart has a module that creates a breaking effect that then deletes the cart. breakCart()
I do not know how to create a system that times a cart if it is not used in a certain amount of time.

Normally you would use Debris for this which you would remove an item within a Period of time using AddItem, But I dont think there is a RemoveItem function so you may have to create a custom Debris and check if the Item is within the Table and if so delete it after that returns true, you might be able to use a loop to constantly check for that update or with the usage of metatables.

stated before, I do not need to destroy the actual object, it has a custom destroy function. I just do not know how to implement it into/create a despawn system.

Still, I dont exactly see the purpose of a custom destroy.

If you do not want to Destroy the Instance, you may be able to use Instance:Remove() which sets the Parent to nil making the Instance still accessible, while Instance:Destroy() deletes it

Instance:Remove() is deprecated and you should instead set the parent to nil manually.

1 Like

it basically breaks into pieces, makes a lego sound, then the pieces are deleted after.

This is a simple system I made in less than 3 minutes:

Ready = false -- Boolean to use

task.delay(10, function()
	Ready = true -- Sets boolean
end)

local spawnfunc = task.spawn(function()
	local timethread = task.delay(15, function() -- Creates Delay thread (delays code inside)
		print"Failed"
        task.cancel(spawnfunc)
	end)
	while task.wait(1) do
		if Ready then -- if true
			task.cancel(timethread) -- cancels timer (delay thread)
			print"cancelled thread!"
			break -- breaks loop
		else -- if false
			print"Waiting..."
		end
	end
end)

Oh then you would have to acces all of the welds and break them (or usebreakJoints())