• Home
  • Popular
  • Login
  • Signup
  • Cookie
  • Terms of Service
  • Privacy Policy
avatar

Posted by User Bot


09 Jan, 2025

Updated at 20 Jan, 2025

Fixing NPC AI Code

Hello guys! I’m currently working on an entity-AI system, but I’ve had some trouble.

Script:

local pathfindingservice = game:GetService("PathfindingService")
local runservice = game:GetService("RunService")
local players = game:GetService("Players")

local npc = script.Parent
local humanoid = npc.Humanoid
local head = npc.Head
local hrp = npc.HumanoidRootPart

local settings = require(npc.Settings)

hrp:SetNetworkOwner(nil)

function findTarget()
	local nearestTarget = nil
	local nearestDistance = math.huge

	for i,v in game.Players:GetPlayers() do
		local character = v.Character
		local humanoid = character and character:FindFirstChildOfClass("Humanoid")

		if humanoid and humanoid.Health > 0 then
			local Distance = (character.HumanoidRootPart.Position - hrp.Position).Magnitude

			if Distance < nearestDistance then
				if settings.checkTarget(character) then
					nearestTarget = v
					nearestDistance = Distance
					return nearestTarget
				end
			end
		end
	end
end

function AttackTarget(target)
	
	if target then
		-- found target
		local char = target.Character
		
		
	else
		warn("no target given.")
	end
end

function targetAngle(character)
	
	print("TARGETANGLE")
	
	local npctocharacter = (character.HumanoidRootPart.Position-hrp.Position).Unit
	local npclook = hrp.CFrame.LookVector
	
	local dot = npctocharacter:Dot(npclook)
	
	local maxdist = 100
	
	local dist = (character.Head.Position-hrp.Position).Magnitude
	
	local direction = (character.Head.Position-hrp.Position)
	
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {npc, character}
	params.FilterType = Enum.RaycastFilterType.Exclude
	
	local ray = workspace:Raycast(hrp.Position, direction*direction.Magnitude, params)
	
	if ray and ray.Instance then
		
		print("RAY TRUE")
		print(ray.Instance.Name)
		
		if dot > .5 then
			print("DOT TRUE")
			if dist <= maxdist then
				-- char is in fov
				print("DIST TRUE")
				return true
			else
				return false
			end
		else
			-- char is not in fov
			return false
		end
		
	else
		-- something is blocking the way
		return false
	end
end

function followTarget()
	
	local target = findTarget()
	
	if target then
		
		if targetAngle(target.Character) then
			print("followTarget")

			local char = target.Character
			local charhead = char.Head

			local path = pathfindingservice:CreatePath(settings.agentparams)
			path:ComputeAsync(hrp.Position, char.HumanoidRootPart.Position)
			local waypoints = path:GetWaypoints()

			humanoid.WalkSpeed = settings.MaxSpeed

			if path.Status == Enum.PathStatus.Success then
				for _, waypoint in pairs(waypoints) do
					if waypoint.Action == Enum.PathWaypointAction.Jump then
						humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
					end
					humanoid:MoveTo(waypoint.Position)
					humanoid.MoveToFinished:Wait()
				end
			else
				warn("Path not found!")
			end
		end
		
	end
	
end

function Patrol()

	print("patrol")

	humanoid.WalkSpeed = settings.PatrolSpeed

	local patrolfolder = workspace.PatrolArea:GetChildren()

	local randompatrol = patrolfolder[math.random(1,#patrolfolder)]

	local path = pathfindingservice:CreatePath(settings.agentparams)
	path:ComputeAsync(hrp.Position, randompatrol.Position)

	local waypoints = path:GetWaypoints()

	if path.Status == Enum.PathStatus.Success then
		for index, waypoint in pairs(waypoints) do

			local target = findTarget()
			
			if target then
				followTarget()
			else
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				end

				humanoid:MoveTo(waypoint.Position)
				humanoid.MoveToFinished:Wait()
			end
		end
	else
		warn("Path not computed!", path.Status)
	end

end

while task.wait() do
	Patrol()
end

I’ve added some prints to understand where the bugs occurred, so please don’t mind those.

I’m having a difficult time comprehending my code, which is a bit embarrassing, but I’m left with no choice.

What I want it to do is find a player that is nearest to the entity, use pathfinding to attempt to attack them, which is blank for now, (I’ll add stuff soon.) The entity cannot detect the player in 3 ways,

  1. A direct ray must be established between the entity and the player so that the entity cannot see through objects.
  2. The entity can see through a limited angle.
  3. A maximum distance, so the entity cannot attack something that is extremely far.

So far, I’ve implemented all three, but the NPC is super buggy, as long as these requirements are met, I’m fine with changing the code.

I’ve tried to look for other solutions but I couldn’t find too much.

Any help is appreciated! :smile:

1 post - 1 participant

Read full topic