Delay when moving NPCs with :MoveTo()

Hello, I am currently making a TD game and I am having some problems with getting the enemies to move along the track.

Currently I am using :MoveTo() to get the enemies to move to the next waypoint, but there is a brief pause from when I call :MoveTo() to when the enemy actually moves.

At first I used Humanoid.MoveToFinished:Wait() to time the movements, and I thought that this was causing the delay, which caused me to switch a system where I use RunService.Heartbeat to constantly check the NPC’s position to see when it has reached the next point, this however yielded the same results leading me to believe that the timing of the movements is not the problem.

I think the problem is with :MoveTo() or Humanoid.WalkToPoint.

Faster Enemies move just fine along the track, but slower enemies pose a problem, meaning there are workarounds but I would prefer to solve the issue instead of just working around it.

I suspect it is a server-side issue as when i play in studio there is no delay, but when I play in an actual roblox server the delay is present.

Here is the code I am using to move the NPC:

-The waypoints are stored as Vector3 positions in a table called “navPath”
-This is a Server Script inside the NPC.

RunService.Heartbeat:Connect(function()
	local nextPoint = nextPointVal.Value + 1
	local np = navPath[nextPointVal.Value]
	local distToPoint = (hrp.Position - Vector3.new(np.X, hrp.Position.Y, np.Z)).Magnitude

	if distToPoint <= towerFuncs.zombieMovementThreshold then

		if nextPoint == #navPath+1 then
			miscFolder.BaseHealth.Value -= hum.Health
			zombie:Destroy()
		else
			nextPointVal.Value = nextPoint
			hum:MoveTo(navPath[nextPoint])
		end
	end
end)

I also have a video of the problem where you can see the delay:

https://www.youtube.com/watch?v=KzfefIGC9WY

I have also tried moving the NPC on the client which didn’t work at all.

Any and all help greatly appreciated!

Thanks!

** EDIT

What I’m hearing is that while there are ways to mitigate this issue, it’s better to use something like TweenService or Lerp, as they use less memory and should yield the same results. Thank you all who replied and gave your feedback, you have been immensely helpful!

Try wrapping it all in a task.spawn so that the script doesn’t yield due to multiple humanoid:moveto() being called. I would recommend continuing to use humanoid:moveToFinished with this method

2 Likes

Actually, refer to this post, it seems to match what you sent

1 Like

I’ve seen many people suggest (specifically for tower defense games) to actively AVOID humanoids for a multitude of problems they have (optimization being one of them).

Really, for TD games, you should be using AnimationControllers for animations and Lerping / Tweening for movement.

If you want to continue using Humanoids because they’re already functional, then setting the RootParts network owner to nil when the enemies spawn may fix the issue.

1 Like

what’s wrong with tweening them? I feel like tweening/lerping might be bette for a TDS game.

1 Like

I was using tweens but I thought using moveto() would use less resources. Think I am wrong though and may just go back.

I try setting the root part networkowner to nil and see if that helps.

Tweens don’t show walking animations unless you use an animation controller. It’s a large reason why most don’t bother with it, humanoid solves for that automatically alongside the animate script

1 Like

Hi!

Humanoids nor Humanoid movers such as :MoveTo() and PathfindingService are least effecient to use in a game that will have a lot of units at the same time. It will cost a lot of memory and in result, it lead to lags.

I assume to use TweenService or CFrame:Lerp(). Both ways wont force Roblox to do unneccessary physics math operations since units are gonna be anchored and won’t have collisions :happy1:

3 Likes

I agree with @YudiFly it’s probably best to use tweening and play animations separately. Additionally, that will make the game even more performant as animation scripts wont have to check for humanoid state changes.

The thing with those methods is that they cause the npcs to turn very sharply but I’m sure I could figure something out to counter this. That was the main reason I was using moveto().

You could add a tween for the rotation inbetween,
eg: tween position from point a to point b, then when reached, tween rotation from rotation a to rotation b, then twen position from point b to point c, etc

Have 1 lerp for rotation which is far more responsive (and fast) than the position lerp, which would be variable per-unit (for example, bosses could be slower than normal enemies, but all enemies rotate at the same rate since it’d be a “global” variable shared across them)