Hello, I am trying to make an NPC following system similar to the roblox game Anime Fighters Simulator where essentially NPCs will always stay at a certain point next to / behind the player, and if the NPC is not at that position, they will move to it. I do not know how to make something like this, I am wondering some tips on how to make this system.
Not really, I was trying to use a script to add a part a few studs next to the player and make the NPC’s humanoidrootpart CFrame to the CFrame of that part, then use Motor6D to make that part stay next to the player, but it didn’t seem to be working. The Motor6D made the the part’s position locked to the exact position of the player’s humanoidrootpart and I could not manipulate it at all. So I really do not know how to get past this or any other ways to make this follow system.
Try this code out, I tested it and it works perfectly fine.
local PS = game:GetService("Players")
local PTS = game:GetService("PathfindingService")
local owner = "Downrest"
local char = script.Parent
local hrp = char.PrimaryPart
local hum = char:FindFirstChildWhichIsA("Humanoid")
local function GoToPath(target)
warn("ayyy")
local path = PTS:CreatePath({
["AgentRadius"] = 2,
["AgentHeight"] = 5,
["AgentCanJump"] = true
})
path:ComputeAsync(hrp.Position, target)
if path.Status ~= Enum.PathStatus.Success then
return
end
local waypoints = path:GetWaypoints()
for _,wp in ipairs(waypoints) do
local magnitude = (hrp.Position - target).Magnitude
if magnitude < 7 then
warn("oops")
break
end
hum:MoveTo(wp.Position)
hum.MoveToFinished:Wait()
end
end
local function TrackPlayer(name)
local target = nil
for i,v in ipairs(PS:GetPlayers()) do
if v.Character and v.Character.Name == name then
target = v.Character.PrimaryPart
end
end
return target
end
while true do
local target = TrackPlayer(owner)
if target then
GoToPath(target.Position)
end
task.wait(.05)
end
What I did was use PathfindingService, loop through the calculated waypoints of the path, then make the loop stop (practically stopping the humanoid from moving) when it is close enough.
local PS = game:GetService("Players")
local PTS = game:GetService("PathfindingService")
local owner = "Downrest"
local char = script.Parent
local hrp = char.PrimaryPart
local hum = char:FindFirstChildWhichIsA("Humanoid")
local function SetNetworkOwnership()
for i,v in ipairs(char:GetDescendants()) do
if v:IsA("BasePart") then
v:SetNetworkOwner(nil)
end
end
end
local function GoToPath(target)
warn("ayyy")
local path = PTS:CreatePath({
["AgentRadius"] = 2,
["AgentHeight"] = 5,
["AgentCanJump"] = true
})
path:ComputeAsync(hrp.Position, target)
if path.Status ~= Enum.PathStatus.Success then
return
end
local waypoints = path:GetWaypoints()
for _,wp in ipairs(waypoints) do
local magnitude = (hrp.Position - target).Magnitude
if magnitude < 7 then
warn("oops")
break
end
hum:MoveTo(wp.Position)
hum.MoveToFinished:Wait()
end
end
local function TrackPlayer(name)
local target = nil
for i,v in ipairs(PS:GetPlayers()) do
if v.Character and v.Character.Name == name then
target = v.Character.PrimaryPart
end
end
return target
end
SetNetworkOwnership()
while true do
local target = TrackPlayer(owner)
if target then
GoToPath(target.Position)
end
task.wait(.05)
end
When this works, remember to remove the extra warn()s I added. They’re just for testing and it will slow down your game (because it’s going to print every .05 seconds).