Laggy NPC movement (towards player)

Hey, I am using a script that I got from another post, and I have this choppy movement with the NPC I am trying to move, this has been asked here many times, but I still struggle to understand how to fix this.

This, while running at ~30 times per second of course, returns laggy movement, even if I bump it up to wait(.5) it still has unpredictable and randomized stutters in the movement.

https://gyazo.com/9899f2cf9933928197829b718d922b46.gif

For the ones who didn’t open the post, this is the code:

local NPC = script.Parent
local Humanoid = script.Parent:WaitForChild("Humanoid")
local HRP = script.Parent:WaitForChild("HumanoidRootPart")

local function GetClosestPlayer(range)
    local List = {}
	local Target = nil
	for i, v in pairs(game.Players:GetPlayers()) do
		local dist = v:DistanceFromCharacter(HRP.position)
		if dist <= range then
			table.insert(List, {dist, v})
		end
	end
		
	table.sort(List, function(A, B)
		return A[1] < B[1]
	end)
	
	pcall(function()
		Target = List[1][2]
	end)
	
	return Target
end

while true do
	wait()
	local Target = GetClosestPlayer(400)
	print(Target)
	if Target ~= nil then
		if Target.Character ~= nil then
			Humanoid:MoveTo(Target.Character.PrimaryPart.Position)
			Humanoid.MoveToFinished:Wait()
		end
	end
end
3 Likes

The only reason I can think of is the line

Humanoid:MoveTo(Target.Character.PrimaryPart.Position)
Humanoid.MoveToFinished:Wait()

There’s a wait

Removing the wait, still causes it to be somewhat laggy on sudden movement.
https://gyazo.com/eff01f4f3479ea5c79cd66e9f09f1b80.gif

you could try using MoveTo(Vector3 + VelocityOffset), where VelocityOffset is the Player’s velocity

1 Like

What do you mean the Player’s velocity? you mean the hrp velocity or something?

yeah pretty much, but you could also use Humanoid.MoveDirection

1 Like

It’s “laggy” because of the MoveToFinished:Wait() call. Essentially what’s happening is you’re giving the humanoid a target position to move to, and then pausing the code while the humanoid walks to the position. While the humanoid is walking, the player is also moving, but the humanoid is continuing to walk to the original player position and doesn’t start walking to the player’s current position until after it has reached the old position.

In the GIF you posted with the MoveToFinished:Wait() removed, it doesn’t appear to be laggy and the humanoid is following the player much more closely, why do you say it is?

The gif is in about 20 fps, i’ll try to get a better shot.
What I mean is this:
https://gyazo.com/d2987ce04b0110610bcee9756c633862.gif
You see the health bar is being choppy, that’s the movement, anyway to fix that as well?

Something that I find very weird is when the

Humanoid:MoveTo()

is called the humanoid doesn’t like it if it’s only given a position. Try doing:

Humanoid:MoveTo(Target.Character.PrimaryPart.Position,Target.Character.PrimaryPart)
Humanoid.MoveToFinished:Wait()

You can also add a number in the Wait() so that the humanoid doesn’t wait for it to go to one position for over 7 seconds.

1 Like

let’s suppose this Red part is the target location, while using Humanoid.MoveDirection we can get a decent result so that the NPC is following ahead of the player

I think you’ll have to post the game, because I don’t see any unusual lag in the GIF.

That seems to randomly freeze the NPC after I jump. (and he starts moving again after I jump later)

https://gyazo.com/47fe9b95cea4d0f5c7b9f7e14b91f703

In my playtest it looked like the NPC was trying to predict the movement of the player :joy:
Essentially, it does work.
https://gyazo.com/72cbcc0ef5ec1c86e2ca2f26f8c86480.gif

at least the NPC is now smart :wink:

2 Likes

Get rid of the Y position. The humanoid doesn’t move to something higher than it’s humanoid root part. Or at least that’s what I see.

How can I get rid of the Y position? I just have the PrimaryPart, from the code you sent here.

Vector3 * Vector3.new(1, 0, 1)

I think you misunderstand what connecting a wait() to an event (MoveToFinished) does. It doesn’t cancel the movement if the time inside the wait() has passed, it yields the thread until the event fires and the number inside the wait() is an additional time to wait after the event fires. So in this case, if you put a MoveToFinished:wait(7) then when the humanoid reaches it’s destination it’s going to stand still for 7 seconds before going back to following.

Nevermind, I assumed that the event:wait() followed the same functionality as a normal wait(), but it simply yields until the event fires (and doesn’t accept any parameters).

Break up the positions

Vector3.new(Target.Character.PrimaryPart.Position.X,0.5,Target.Character.PrimaryPart.Position.Z)

Uh, this seems to make it worse… (Woah, apologize for the gif quality…)
https://gyazo.com/28259776c93f9722dc0d10fea143ff25.gif