MoveTo Tiny NPC

I am working on this game where all NPC’s have a humanoid but are on a small scale, for ex;
image

And I have some waypoints that I want other npcs to walk to, like a tower defense game;

How would I move them on those points? Since they are small they break and do not stay on the lines, should I use tween if so how?

2 Likes

You can use TweenService with linear interpolation.

Number all of your points with rising numbers from start to end. Then use a for loop to tween the NPC based on a movement speed parameter calulated with the distance between the points to get a move time value.

There shouldn’t be any problems with using MoveTo() if you scale it correctly, just make sure every part is unanchored.

1 Like

I tried, put 5 points make them walk to each of them, they don’t fully touch it.

He’s probably not using a scaled humanoid character tho.

I mean a default R6 Rig

That’s a different problem now, this should be caused by your script. Maybe MoveToFinished timeout causing it?


At least in the first image he’s showing a R6 Character.

1 Like

You can try using pathfinding modifiers to prevent the NPC from going on the unintended path.

here is my code:

for waypoint = 1, #waypoints:GetChildren() do
		mob.MovingTo.Value = waypoint
		humanoid:MoveTo(waypoints[waypoint].Position)
		humanoid.MoveToFinished:Wait()
	end

even with a 10 second wait it just hovers in place and doesnt full touch it

Wait did you adjust the hipheight of the NPC?

I did not, let me try something.

1 Like

Doesnt change it still broken, what do I do?

1 Like

Welp, im coming back from school so i cant really help you atm. Hopefully someone reaches out to you soon.

Maybe send a screenshot on how the NPC behaves when pathing

see they do not fully touch it and go on to the next one

1 Like

As I said, this is being caused by MoveToFinished’s timeout, at the end of the page there’s a function to prevent this.

local function MoveTo(humanoid: Humanoid, targetPoint: Vector3, andThen: () -> any?)
	local targetReached = false

	-- listen for the humanoid reaching its target
	local connection
	connection = humanoid.MoveToFinished:Connect(function(reached)
		targetReached = true
		connection:Disconnect()
		connection = nil
		if andThen then
			andThen()
		end
	end)

	-- start walking
	humanoid:MoveTo(targetPoint)

	-- execute on a new thread so as to not yield function
	task.spawn(function()
		while not targetReached do
			-- does the humanoid still exist?
			if not (humanoid and humanoid.Parent) then
				break
			end
			-- has the target changed?
			if humanoid.WalkToPoint ~= targetPoint then
				break
			end
			-- refresh the timeout
			humanoid:MoveTo(targetPoint)
			task.wait(6)
		end

		-- disconnect the connection if it is still connected
		if connection then
			connection:Disconnect()
			connection = nil
		end
	end)
end

local Humanoid -- your humanoid
local TargetPos -- your target position

MoveTo(Humanoid, TargetPos, function()
	print("Finished")
end)
2 Likes

How would I implemnt this into my code? Here it is;

function mobHandler.Move(mob, map)
	local humanoid = mob:WaitForChild("Humanoid")
	local waypoints = map.Waypoints
	
	for waypoint = 1, #waypoints:GetChildren() do
		mob.MovingTo.Value = waypoint
		humanoid:MoveTo(waypoints[waypoint].Position)
		humanoid.MoveToFinished:Wait()
	end
	
	mob:Destroy()
	
	map.Base.Humanoid:TakeDamage(humanoid.Health)
end

You could try move to way point

I made a quick function for your iteration;

local function Iterate(humanoid, t: { Vector3 } , n: number?, andThen: any?)
	n = n or 1
	
	assert(n)
	
	if n > #t then if andThen then andThen() end return end -- if all waypoints have been reached
	
	MoveTo(humanoid, t[n].Position, function()
		Iterate(t, n + 1, andThen)
	end)
end

Also, instead of what you’re doing I would opt for an iterative loop using ipairs/pairs, but with your example you could skip this and opt for the function’s recursion.

Iterate(humanoid, waypoints:GetChildren(), 1, function ()
	mob:Destroy()
	map.Base.Humanoid:TakeDamage(humanoid.Health)
end)

Ok i think i found the solution, try making the agent pathfinding width smaller.

See here:
https://developer.roblox.com/en-us/api-reference/function/PathfindingService/CreatePath

(This also implies you change your script to use PathfindingService instead of MoveTo)

So like this?

local function Iterate(humanoid, t: { Vector3 } , n: number?, andThen: any?)
	n = n or 1

	assert(n)

	if n > #t then if andThen then andThen() end return end -- if all waypoints have been reached

	MoveTo(humanoid, t[n].Position, function()
		Iterate(t, n + 1, andThen)
	end)
end

function mobHandler.Move(mob, map)
	local humanoid = mob:WaitForChild("Humanoid")
	local waypoints = map.Waypoints

	Iterate(humanoid, waypoints:GetChildren(), 1, function ()
		mob:Destroy()
		map.Base.Humanoid:TakeDamage(humanoid.Health)
	end)
end

The part: MoveTo(humanoid, t[n].Position, function() errors moveto