I want to make an advanced Enemy AI, I instantly want to start by saying that this AI is very similar to that of the ‘Hello Neighbor’ AI, with there being 4 modes: Idle, Hunt, Chase, Offline. Idle is the only relevant one here. Idle mode means the AI is doing tasks within the ‘house’ location. I already have some tasks:
- Cook Food
- Watch TV
- Fix Car
- Look through boxes
The issue is roblox’s pathfinding. Maybe it’s just me or the physical NPC im using (An r6 roblox character, HumanoidRootPart being the only collidable object). But the AI is often bumping into walls ext.
I’ve tried fixing the pathfinding with agent parameters but not much difference is made.
I do not NEED the AI to pathfind between each task, opting for a method where the AI walks between pathfinding connectors which are close and easy to walk to without pathfinding error, and then when the opportunity presents itself, the AI will move towards a task part. I just want the AI to have tasks and work.
Main Idle mode module:
-- local idle = {}
local waypoint_folder = workspace.WaypointsFolder
local ai_utils = require(script.Parent.other)
local downstairs_activities = {
"tv",
"fruit",
"box",
}
local upstairs_activities = {
"sink",
"sleep",
}
function idle.setup(npc_stats)
local humanoid = npc_stats.npc.Humanoid
end
function idle.activity(npc_stats)
npc_stats.can_do_activity = false
local chance_of_changing_floor = math.random(1, npc_stats.chance_of_changing_floor)
if chance_of_changing_floor == 1 then
ai_utils.change_floor(npc_stats, function(result)
if result == false then
idle.activity(npc_stats)
return
elseif result == true then
task.wait(1)
play_activity(npc_stats)
end
end)
else
task.wait(1)
play_activity(npc_stats)
end
end
function play_activity(npc_stats)
local activities
if npc_stats.current_floor == 1 then
activities = downstairs_activities
else
activities = upstairs_activities
end
local random_activity = math.random(1,#activities)
local activity_function = activities[random_activity]
if activity_function == npc_stats.last_activity then
idle.activity(npc_stats)
return
end
npc_stats.last_activity = activity_function
idle[activity_function](npc_stats)
end
function idle.tv(npc_stats)
local tv_part = waypoint_folder.tasks.downstairs.watch_tv.chair
local hum : Humanoid = npc_stats.npc.Humanoid
ai_utils.pathfind(npc_stats, tv_part.Position, npc_stats.agent_paramaters, function(result)
if result == true then
task.wait()
--npc_stats.npc.HumanoidRootPart.Orientation = Vector3.new(0, tv_part.Orientation.Y, 0)
npc_stats.npc.HumanoidRootPart.CFrame = tv_part.CFrame * CFrame.new(0,2.5,0)
task.wait(10)
npc_stats.can_do_activity = true
elseif result == false then
npc_stats.can_do_activity = true
end
end)
end
function idle.fruit(npc_stats)
local fruit_part = waypoint_folder.tasks.downstairs.take_fruit.fruit
local hum : Humanoid = npc_stats.npc.Humanoid
ai_utils.pathfind(npc_stats, fruit_part.Position, npc_stats.agent_paramaters, function(result)
if result == true then
task.wait()
--npc_stats.npc.HumanoidRootPart.Orientation = Vector3.new(0, tv_part.Orientation.Y, 0)
npc_stats.npc.HumanoidRootPart.CFrame = fruit_part.CFrame * CFrame.new(0,2.5,0)
task.wait(10)
npc_stats.can_do_activity = true
elseif result == false then
npc_stats.can_do_activity = true
end
end)
end
function idle.box(npc_stats)
local box_part = waypoint_folder.tasks.downstairs.search_box.box
local hum : Humanoid = npc_stats.npc.Humanoid
ai_utils.pathfind(npc_stats, box_part.Position, npc_stats.agent_paramaters, function(result)
if result == true then
task.wait()
--npc_stats.npc.HumanoidRootPart.Orientation = Vector3.new(0, tv_part.Orientation.Y, 0)
npc_stats.npc.HumanoidRootPart.CFrame = box_part.CFrame * CFrame.new(0,2.5,0)
task.wait(10)
npc_stats.can_do_activity = true
elseif result == false then
npc_stats.can_do_activity = true
end
end)
end
-- UPSTAIRS
function idle.sink(npc_stats)
local sink_part = waypoint_folder.tasks.upstairs.wash_hands.sink
local hum : Humanoid = npc_stats.npc.Humanoid
ai_utils.pathfind(npc_stats, sink_part.Position, npc_stats.agent_paramaters, function(result)
if result == true then
task.wait()
--npc_stats.npc.HumanoidRootPart.Orientation = Vector3.new(0, tv_part.Orientation.Y, 0)
npc_stats.npc.HumanoidRootPart.CFrame = sink_part.CFrame * CFrame.new(0,2.5,0)
task.wait(10)
npc_stats.can_do_activity = true
elseif result == false then
npc_stats.can_do_activity = true
end
end)
end
function idle.sleep(npc_stats)
local sleep_part = waypoint_folder.tasks.upstairs.sleep.floor
local sleep_part2 = waypoint_folder.tasks.upstairs.sleep.bed
local hum : Humanoid = npc_stats.npc.Humanoid
ai_utils.pathfind(npc_stats, sleep_part.Position, npc_stats.agent_paramaters, function(result)
if result == true then
-- Pathfinding successful
task.wait()
-- Adjust NPC position
npc_stats.npc.HumanoidRootPart.CFrame = sleep_part.CFrame * CFrame.new(0,2.5,0)
-- Slight wait
task.wait(5)
npc_stats.can_do_activity = true
elseif result == false then
-- Pathfinding Unsuccessfull
npc_stats.can_do_activity = true
end
end)
end
return idle
Also, if anyone wants to give some tips or critiques on how this is coded, feel free. (The idle module is within the main module which is ran through a runservice loop.