How do I stop an object tweening when it is destroyed?

I am creating a tower defense game where enemies spawn from a part and tween to nodes on the path until they reach the player base. The issue is, when I destroy the enemy after its health has hit 0, although its destroyed, the health of the player base still goes down as if the enemy still made its way to the base. I am not sure how I would destroy the enemy AND stop it from tweening so it does not reach the player base.

This is the tower module script

local rs = game:GetService("ReplicatedStorage")
local towerData = require(script.Parent.towerData)
local tower = {}

local enemies = workspace.Enemies

function findNearestEnemy(newTower)
	local range = 20
	local nearestEnemy = nil

	for i, enemy in ipairs(enemies:GetChildren()) do
		local distance = (enemy.Position - newTower.Position).Magnitude

		if distance <= range then
			nearestEnemy = enemy
		end
	end

	return nearestEnemy
end

tower.Attack = function(newTower)
	local target = findNearestEnemy(newTower)

	if target then
		target.Health.Value -= 3
		
		local targetHP = target.Health.Value
		
		if targetHP <= 0 then
			target:Destroy()
		end
	end

	task.wait(1)
	
	tower.Attack(newTower)
end

This is the enemy movement module script

local rs = game:GetService("ReplicatedStorage")
local ts = game:GetService("TweenService")
local path = workspace.Node1
local enemyData = require(script.Parent.enemyData)
local enemy = {}

local speed = 0.5
local rotationSpeed = 0.2

local currentHealth = 200

enemy.Spawn = function()
	local enemies = {rs.Enemies.Grass, rs.Enemies.Rock}
	local enemy = enemies[math.random(1, #enemies)]:Clone()
	enemy.CFrame = path.CFrame
	enemy.Parent = workspace.Enemies
	
	local enemyHealth = Instance.new("IntValue")
	enemyHealth.Name = "Health"
	enemyHealth.Parent = enemy
	enemyHealth.Value = enemyData.Data[enemy.Name]["Health"]
end

enemy.Move = function(enemy)
	local node = path
	local enemySpeed = enemyData.Data[enemy.Name]["Speed"]
	local finished = false

	while not finished do
		local nodes = node:GetChildren()
		if #nodes > 0 then
			node = nodes[math.random(1, #nodes)]
			local parent = node.Parent
			local distance = (parent.Position - node.Position).Magnitude

			local rotation = CFrame.new(parent.Position, node.Position)
			local rotateTween = ts:Create(enemy, TweenInfo.new(rotationSpeed, Enum.EasingStyle.Linear), {CFrame = rotation})
			rotateTween:Play()
			rotateTween.Completed:Wait()

			local moveTween = ts:Create(enemy, TweenInfo.new(distance*(speed/enemySpeed), Enum.EasingStyle.Linear), {Position = node.Position})
			moveTween:Play()
			moveTween.Completed:Wait()
		else
			finished = true
			currentHealth -= enemyData.Data[enemy.Name]["Health"]
			rs.Events.updateScreen:FireAllClients(currentHealth)
			enemy:Destroy()
		end
	end
end

return enemy

You could try

enemy:GetPropertyChangedSignal("Parent"):Connect(function()
	if not enemy.Parent then
		if rotateTween.PlaybackState == Enum.PlaybackState.Playing then
			rotateTween:Cancel()
		end
		if moveTween.PlaybackState == Enum.PlaybackState.Playing then
			moveTween:Cancel()
		end
	end
end)

Add a :Cancel() when the ememy dies. Tween over.

Enemy.Parent would be the folder they are in in the workspace. Wouldn’t not enemy.Parent always evaluate to false?

if not enemy.Parent then

is equivalent to

if enemy.Parent == nil then

That makes more sense. But where would I put that line of code? Inside the enemy.Move function or just inside the module script? Because there are multiple enemies that are all running that function in the background.

I cannot really give you a clear answer as of now. You have to disconnect the function each time a new loop runs.

Tysm for the help lol. I realized a much easier and efficient solution would be to check if the enemy has a parent in addition to checking if it is not at the end. When it is destroyed the enemy.Parent condition would be nil and the loop would break. I didn’t realize that you could check for an objects parent as a conditional until you mentioned it!

1 Like

I’m glad you figured out a solution on your own, while you got a hint in a direction you could go. Most of the time that is the best way of learning.

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.