Make AI walk in a specific radius

I have made AI in my game, but I am stuck on civilian AI as I want them to walk around in a radius where they spawn at to make sure they don’t wander off.


This is how I want it to be, and I just want to know how this would be achievable

1 Like

Have you tried (Position0 - Position1).Magnitude?
https://developer.roblox.com/en-us/articles/Magnitude

Yes I know what magnitude is, I am just trying to find a position that is in the “radius” (or magnitude) of the AI

The radius of the initial position of that AI? If so, save the position and check it from there.

Okay, so how do I get the position of where I will move the AI to?

Depends on how your AI works. With direct uncaclulated movement you can use Humanoid:MoveTo, otherwise PathfindingService is your better option.

if just wanting to move in a certain radius do something like

local OriginalPos =  HumanoidRootPart.Position   -- do this on initial run
-- to get a new random by radius maybe something like this
local Radius = 10
local NewPosition = OriginalPos + Vector3.new(math.random(-Radius , Radius), OriginalPos .Y, math.random(-Radius , Radius))

you could also do this on Y axis but i choose just to set it what HRP is at

if trying to make sure a position they are headed to is in that radius

if (OriginalPos  - NewPosition).Magnitude > Radius then
  -- call to get a new position this one is outside radius
end

This video might help you

This video makes NPC’s on the client side so they will use a very small amount of network and server resources

It also unloads the NPC’s when you player walks far away from the NPC so the client will only calculate the path of NPC’s there standing close to

If you’re not looking for advanced pathfinding you can just use :MoveTo

local Hum = script.Parent.Humanoid
local Limit = script.Parent.Limit -- Part inside your character that defines the origin

local Radius = 10

function gotoRandom_Pos()
	local X = math.random(Limit.Position.X-Radius,Limit.Position.X+Radius)
	local Z = math.random(Limit.Position.Z-Radius,Limit.Position.Z+Radius)
	
	Hum:MoveTo(Vector3.new(X,0,Z))
end

game:GetService("RunService").Heartbeat:Connect(function()
	if (script.Parent.PrimaryPart.AssemblyLinearVelocity*Vector3.new(1,0,1)).Magnitude <= 1 then
		gotoRandom_Pos()
	end
end)

Just make sure the PrimaryPart is the Humanoid and there’s an anchored part named Limit in your character

1 Like

When I return the waypoints of this
path:ComputeAsync(Mob.HumanoidRootPart.Position, Vector3.new(X,0,Z))
it prints {}.
Does it not work with vector3’s?

So if you want the player to move in a circle, I would suggest using the unit circle theory. Lmk know if there is any errors

local PathfindingService = game:GetService("PathfindingService")

while wait() do
local character = script.Parent --- ur character
local Cx, Cz = 0, 0
local radius = 10
local angle = math.random(0,2*math.pi)
local x, y, z = math.cos(angle ) * radius , character.PrimaryPart.Position.Y, math.sin(angle) * radius
local humanoid = character.Humanoid --- ur humanoid

local success, errorMessage = pcall(function()
		path:ComputeAsync(character.PrimaryPart.Position, Vector3.new(x,y,z))
	end)

if success and path.Status == Enum.PathStatus.Success then
		-- Get the path waypoints
		waypoints = path:GetWaypoints()
if not reachedConnection then
			reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
				if reached and nextWaypointIndex < #waypoints then
					-- Increase waypoint index and move to next waypoint
					nextWaypointIndex += 1
					humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
				else
					reachedConnection:Disconnect()
					blockedConnection:Disconnect()
				end
			end)
		end
 
		-- Initially move to second waypoint (first waypoint is path start; skip it)
		nextWaypointIndex = 2
		humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
	else
		warn("Path not computed!", errorMessage)
	end
end

Path not computed! nil
Again, I don’t know why pathfindingservice is acting weird when the 2nd parameter is a vector3.

ComputeAsync accepts only Vector3

local Hum = script.Parent.Humanoid
local Limit = script.Parent.Limit -- Part inside your character that defines the origin
local PathService = game:GetService("PathfindingService")

local path = PathService:CreatePath{
	AgentRadius = 2.0,
	AgentHeight = 5.0,
	AgentCanJump = false
}

local Radius = 50

function gotoRandom_Pos()
	local X = math.random(Limit.Position.X-Radius,Limit.Position.X+Radius)
	local Z = math.random(Limit.Position.Z-Radius,Limit.Position.Z+Radius)
	
	path:ComputeAsync(script.Parent.PrimaryPart.Position, Vector3.new(X,0,Z))
	if path.Status ~= Enum.PathStatus.Success then return end
	
	for _,v in path:GetWaypoints() do
		Hum:MoveTo(v.Position)
	end
end

game:GetService("RunService").Heartbeat:Connect(function()
	if (script.Parent.PrimaryPart.AssemblyLinearVelocity*Vector3.new(1,0,1)).Magnitude <= 1 then
		gotoRandom_Pos()
	end
end)

The only problem I face now is path:GetWaypoints() occasionally returning {}.

Here take a look at this game. I fixed all the errors
Radius_Dummy (1).rbxl (48.8 KB)

2 Likes

image

This is the problem I sometimes have aswell. It finds the correct path but just refuses to follow it.

Are you using MoveToFinished??

1 Like

Can u send me the file? char

It’s as Msorky said, the solution to fix it is by using MoveToFinished:Wait(), but this makes it “slow” and wait for each waypoint

Do u still need it fixed? Or r u fine?

1 Like