How would i make this AI efficient?

I’m creating an AI script for my npc but when I used a while wait do loop, it makes the npc very choppy and it doesn’t run too great. So I tried using the run service and that makes it a lot less choppy but it makes the npc act funny. Here is some footage

robloxapp-20200514-1734218.wmv (4.2 MB)

(Sorry you have to download it, it wouldn’t let me upload an mp4 :frowning:)

----Wait for game to load
wait()
----Variables
local run = script.Parent.Humanoid:LoadAnimation(script.Parent.Animations.Run)
local walk = script.Parent.Humanoid:LoadAnimation(script.Parent.Animations.Walk)
local service = game:GetService("PathfindingService")
local players = game.Players:GetPlayers()
local human = script.Parent.Humanoid
local hrp = script.Parent.HumanoidRootPart
----Functions
function Roam(target)
	human.WalkSpeed = 5
	walk:Stop()
	if (target.Position - hrp.Position).Magnitude <= 70 then return end
	wait(2)
	local X = math.random(-20,20)
	local Z = math.random(-20,20)
	local path = service:CreatePath()
	local goal = hrp.Position + Vector3.new(X,0,Z)
	path:ComputeAsync(hrp.Position,goal)
	if path.Status == Enum.PathStatus.Success then
		print("Success")
		local points = path:GetWaypoints()
		for _, point in ipairs(points) do
			if point.Action == Enum.PathWaypointAction.Jump then
				human.Jump = true
				print("Jump")
			end
			human:MoveTo(point.Position)
			run:Stop()
			walk:Play()
			if (target.Position - hrp.Position).Magnitude <= 70 then return end
			local finished = human.MoveToFinished:Wait()
			if not finished then
				human.Jump = true
				Roam()
			end
		end
	else
		print("Path failed")
		Roam()
	end
end
----
function Attack(target)
	human.WalkSpeed = 30
	local path = service:CreatePath()
	local goal = target.Position
	path:ComputeAsync(hrp.Position,goal)
	if path.Status == Enum.PathStatus.Success then
		local points = path:GetWaypoints()
		for _, point in ipairs(points) do
			if point.Action == Enum.PathWaypointAction.Jump then
				human.Jump = true
			end
			human:MoveTo(point.Position)
			walk:Stop()
			run:Play()
			local finished = human.MoveToFinished:Wait()
			if not finished then
				Roam()
			end
		end
	else
		print("Chase interupted")
		Roam()	
	end
end
----
function Scan(target)
	if (target.Position - hrp.Position).Magnitude > 70 then
		Roam(target)
	elseif (target.Position - hrp.Position).Magnitude <= 70 then 
		Attack(target)	
	end
end
----
game:GetService("RunService").Stepped:Connect(function()
	for i,p in pairs(players) do
		if p and p.Character and p.Character.HumanoidRootPart then
			Scan(p.Character.HumanoidRootPart)
		end
		wait(2)
	end
end)

Here is the code to it, If anyone knows what I should use instead of the run service then please tell me! It would be greatly appreciated! Thanks! - ScriptToon

When I was using PathFinding service for my NPC’s they were choppy, I fixed that by instead of doing local finished = human.MoveToFinished:Wait(), I changed it to local finished = human.MoveToFinished:Wait(0.01). The default roblox wait() time is 0.30 seconds, so that may cause it to appear choppy.

Adding onto what I said, you also could use Raycast in your script! You could do this to detect if there is a straight path to the player, and if there is then go straight to the player, otherwise compute a path to the player.

Hey ScriptToon!

So what you’re experiencing right now is the overwhelmingly fast speed that Stepped can run at.

What I assume is happening is that it’s swapping from Roaming, to Attacking, and then back to Roaming because your variable finished I don’t think is being registered as true as soon as you need it to be.

A quick fix for this would be to add an additional argument to your :Wait() and then making it :Wait(0.1) which will give your script time to catch up and register the variable properly.

1 Like

Would run service be better than a while loop or vice versa?