--By Rjj259_YT
--Main Variables--
local physicsService = game:GetService("PhysicsService")
local serverStorage = game:GetService("ServerStorage")
local mobHandler = {}
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
function mobHandler.Spawn(name, quantity,map)
local mobExists = serverStorage.mobs:FindFirstChild(name)
if mobExists then
for i = 1, quantity do
task.wait(0.5)
local cloneMob = mobExists:Clone()
cloneMob.HumanoidRootPart.CFrame = map.Start.CFrame
cloneMob.Parent = workspace.Mobs
cloneMob.HumanoidRootPart:SetNetworkOwner(nil)
local movingTo = Instance.new("IntValue")
movingTo.Name = "MovingTo"
movingTo.Parent = cloneMob
for i, object in ipairs(cloneMob:GetDescendants()) do
if object:IsA("BasePart") then
physicsService:SetPartCollisionGroup(object, "Mob")
end
end
cloneMob.Humanoid.Died:Connect(function()
task.wait(0.5)
cloneMob:Destroy()
end)
coroutine.wrap(mobHandler.Move)(cloneMob, map)
end
else
warn("Requested mob does not exist: ", name)
end
end
return mobHandler
You’ve not declared the MoveTo function shown in this post: MoveTo Tiny NPC - #15 by Sarchyx. It’s also warning because I forgot to change the table’s values typecheck, you can remove it if you want.
It still does it and when it gets to the spot where it turns before hitting it an error:
I also delcared it now:
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)
Do you have any scenario where your maps will not be flat? Like perhaps a map with a hill or something?
If your maps are relatively simple or you’re willing to add waypoints before and after hills (and along the hill if the hill is not a straight line) then you could get away with not using Humanoids at all. Humanoids are actually quite expensive and require physical simulation which will generally start to slow a game down after the first 100 or so humanoid characters (pre-optimizations such as disabling most of the humanoid states).
If you are willing to put in more waypoints you can pretty easily use a much faster method such as the TweenService. Here’s an example of how you could do what you’re wanting using the tween service and some recursive CFraming (for smooth turning). WaypointWalkersExample.rbxl (39.0 KB)
Take a look at that example, look through the CharacterController script in Workspace and see what you think. I can help you to understand it better if it isn’t making sense. I tried to use nice variable names to simplify it.
You’ll still want an AnimationController to animate your characters but I would do that separately.
You also mentioned that the characters are different sizes so you’d also want to be able to supply a character height offset to the waypoints. I can help you with that if you need it.