Tower Defense Enemy Movement Issue

  1. What are you trying to achieve? Keep it simple and clear!
    I want to make a tower defense enemy (in this case a default r6 block rig) move respectively to each waypoint. I did the movement itself, but the rotation is a big problem.

  2. What is the issue? Include screenshots / videos if possible!
    The rotation is supposed to face the same orientation as the waypoint (to prevent too much complexity). However, instead of rotating how it’s supposed, it spins around and then stays in that orientation for the rest of his journey.
    robloxapp-20210629-1559151.wmv (716.3 KB)

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried to replace Tween2’s ‘subject’ with the NPC’s torso instead of the rootPart. The rotation works, but if a walking animation plays, it breaks and the limbs get into weird un-intended positions.
    what
    My second attempt to fix it is to simply use BodyGyro, parenting it to the HumanoidRootPart. No matter if the BodyGyro’s was parented to the HumRootPart or Torso, it doesn’t rotate. However the animation works.
    I couldn’t find any DevForum post that matches this problem.

These are the objects of the NPC:
objects

(Animation script is nothing fancy, it just plays the animation.)

nextPoint = 1

-- SETTINGS --
local speed = 6

function moveToPoint()
	
	local TweenService = game:GetService("TweenService")
	
	local Part = script.Parent
	
	local goal = {}
	goal.CFrame = CFrame.new(game.Workspace.Waypoints:FindFirstChild(nextPoint).Position.X, Part.Position.Y, game.Workspace.Waypoints:FindFirstChild(nextPoint).Position.Z)
	
	local goal2 = {}
	goal2.Orientation = Vector3.new(0, game.Workspace.Waypoints:FindFirstChild(nextPoint).Orientation.Y, 0)
	
	local partDistance = (Part.Position - game.Workspace.Waypoints:FindFirstChild(nextPoint).Position).magnitude
	
	local tweenInfo = TweenInfo.new(partDistance / speed, Enum.EasingStyle.Linear)
	local tweenInfo2 = TweenInfo.new(1, Enum.EasingStyle.Quad)
	
	local tween = TweenService:Create(Part, tweenInfo, goal)
	local tween2 = TweenService:Create(Part, tweenInfo2, goal2) --Works if i put "Script.Parent.Parent.Torso" instead of Part.
	
	tween2:Play()
	tween:Play()
	
	wait(partDistance / speed)
	
	nextPoint = nextPoint + 1
	
	if game.Workspace.Waypoints:FindFirstChild(nextPoint) ~= nil then
		moveToPoint()
	else
		script.Parent.Parent:Destroy()
	end
end

moveToPoint()
1 Like

How about use Humanoid:MoveTo() which is simpler?

2 Likes

I wanted to, but i realized Humanoid:MoveTo() stops if the npc is still walking after about 6-8 seconds. This would probably be a problem, especially for the slower enemies.
I also think Humanoid:MoveTo() causes lag if fired too much.

How about this?


I don’t think so.

I already had the solution for the timeout, i was just worried if the loop would lag the game. And…
Ah, so the game doesn’t lag if i fire Humanoid:MoveTo() at a interval of very few milliseconds?

Well, I would say to fire the the function at around 6 seconds. That should be good!

There is a problem:
The NPC sometimes has a delay before switching waypoints because of the while loop waiting

You definitely don’t need to fire it that often, really you only need to do it when they reach the point. Not sure about a delay between it however.

1 Like

That’s true, i shouldn’t fire it too much.

Alright, i’ve made the new movement system in which works both movement and rotation thanks to your advice. Animation work too.

Here’s what i did if it interests you:

  • Instead of using the While Loop to fire the Move function i used Humanoid.Running event, that detects if the NPC stopped moving or not. This is useful for the timeout and probably better than using While Loop.
  • There was a issue with :MoveTo(), and that is the fact that the NPC doesn’t move to the exact Y axis of the waypoint instead it stops in front of the waypoint. This led me to use magnitude: when the NPC is 1 stud close of the waypoint, it moves to the next point (I moved the waypoint a stud back from the center of the tile so the NPC moves on the center of the road). This can be tricky for the future big enemies but i can just change the required distance for that.

Besides these, thanks for your advice!

Here’s the current code:

nextPoint = 1

db = true

function moveToPoint()
	db = false
	local NPC = script.Parent
	local Point = game.Workspace.Waypoints:FindFirstChild(nextPoint).Waypoint
	NPC.Enemy:MoveTo(Point.Position)
	
	local partDistance = (NPC.Torso.Position - game.Workspace.Waypoints:FindFirstChild(nextPoint).Waypoint.Position).magnitude
	if partDistance <= 1 then
		
		nextPoint = nextPoint + 1
		
		if game.Workspace.Waypoints:FindFirstChild(nextPoint) == nil then
			script.Parent:Destroy()
		else
			moveToPoint()
		end
	end
	
end

script.Parent.Enemy.Running:Connect(function(speed)
	if db then return end
	if speed == 0 then
		print("Firing Function")
		moveToPoint()
	end
end)

moveToPoint()

And here’s the dummy in action:
dummy-in-action.wmv (622.7 KB)