Tower Defense Tweening/Animating Enemies

Questions

  • how to move the enemies at a consistent speed
  • How do you animate the character while its tweening without a humanoid?

image

Problems

what else can i use besides tweening since its not very consistent with the speed of the character
how do i plant or give the character gravity so they touch the ground

i figured out the animating part but i used animation controller:LoadAnimation()
but is that deprecated? If so what should i use instead?

	local Test = game:GetService("ServerStorage").Enemies.Test:Clone()
	Test.Parent = workspace.Enemies
	Test:PivotTo(workspace.EnemySpawn.CFrame)

	local animator = Test.AnimationController
	local animTrack = animator:LoadAnimation(animator.Walk):Play()
	
	coroutine.wrap(function()
		for currentpoint = 1, #workspace.Pathpoints:GetChildren() do
			local targetCFrame = workspace.Pathpoints[currentpoint].CFrame

			local tweenInfo = TweenInfo.new(
				3,
				Enum.EasingStyle.Linear,
				Enum.EasingDirection.Out
			)

			-- Create the tween
			local tween = TweenService:Create(
				Test.PrimaryPart,
				tweenInfo,
				{ CFrame = targetCFrame }
			)
			tween:Play()
			tween.Completed:Wait()
		end
	end)()

	task.wait(0.5)
1 Like

You can get the direction to the next node and add it to the CFrame with a speed multiplier.
Do this every frame and it will move at a constant speed.

For this, you need to do some math (not too complicated), here is an example:

local distance = (PreviousWaypoint.Position - NextWayPoint.Position).Magnitude — Distance calculation

local speed = 10 — enemy speed (you can change using modules or however you want)

local TravelTime = distance/speed

1 Like

And for the question, you can use CFrame:Lerp(), and you have to load the animation on the animator inside of the player/enemy.

local animator = plr.Humanoid:FindFirstChild(“Animator”) or Instance.new(“Animator”, plr.Humanoid)

(I’m on mobile so sorry for not code blocking)

not really sure what you mean by getting the direction and adding it to the cframe

how would i store the previouswaypoint with my script?

Before the coroutine, add a local variable called previousWaypoint, and after the tween is completed inside the move function, set the previousWaypoint to that waypoint

Also, I recommend only using positions and then using the CFrame property :LookAt() to look at the waypoint, and if you choose to use CFrame:Lerp() then you can construct a CFrame from that

and what is the use of traveltime? i can’t calculate the traveltime until they have reached a new checkpoint to get the previous checkpoint?

If previousCheckpoint == nil then previousCheckpoint = enemyspawnpoint end

Actually you could just set it to enemyspawn before the for loop to save server resources

is travel time going to be used in the tween info?

Yes, thats the whole reason for the calculations, set TravelTime to the time the tween takes

how would i use lookAt() with this?

I’m on mobile but I’ll try my best to show how the move function could look

1 Like
local distance = (PreviousWaypoint.Position - NextWayPoint.Position).Magnitude — Distance calculation

local speed = 10 — enemy speed (you can change using modules or however you want)

local TravelTime : number = distance/speed

			local tweenInfo = TweenInfo.new(
				TravelTime,
				Enum.EasingStyle.Linear,
				Enum.EasingDirection.Out
			)

			-- Create the tween
			local tween = TweenService:Create(
				Test.PrimaryPart,
				tweenInfo,
				{ Position = CurrentPoint.Positon }
			)

local rot = CFrame.lookAt(PreviousWaypoint.Position, CurrentPoint.Position)

Test.PrimaryPart.CFrame = Test.PrimaryPart.CFrame * rot

			tween:Play()
			tween.Completed:Wait()

PreviousWaypoint = CurrentPoint


i tried this its pretty buggy

for i = 1, 3 do
	local Test = game:GetService("ServerStorage").Enemies.Test:Clone()
	Test.Parent = workspace.Enemies
	Test:PivotTo(workspace.EnemySpawn.CFrame)
	local previous_waypoint = workspace.EnemySpawn
	
	coroutine.wrap(function()
		for currentpoint = 1, #workspace.Pathpoints:GetChildren() do
			
			local distnace = (previous_waypoint.Position - workspace.Pathpoints[currentpoint].Position).Magnitude -- distance calculation
			local speed = Test:GetAttribute("Speed") -- enemy speed
			local TravelTime = distnace/speed
			
			local info = TweenInfo.new(
				TravelTime,
				Enum.EasingStyle.Linear,
				Enum.EasingDirection.Out
			)
			
			local tween = TweenService:Create(
				Test.PrimaryPart,
				info,
				{CFrame = workspace.Pathpoints[currentpoint].CFrame}
			)
			tween:Play()
			tween.Completed:Wait()
			local rot = CFrame.lookAt(previous_waypoint.Position, workspace.Pathpoints[currentpoint].Position)

			Test.PrimaryPart.CFrame = Test.PrimaryPart.CFrame * rot

			previous_waypoint = workspace.Pathpoints[currentpoint]
		end
		Test:Destroy()
	end)()

	task.wait(0.5)
end

when they reach the waypoint they teleport away far away and then walk to the next one

Its something with the lookAt function, quote it out and see if it atleast moves to the positions (actually with these modifications you can just entirely remove the lookAt function)

i tried it and yes they do move to every point

Does it look fine?