Npc state machine

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want to make an npc state machine where npcs could either: talk to eachother, or B, pathfind to a random position
    Also the npcs are in a folder, like im trying to make a script that controls them from the folder
  2. What is the issue? Include screenshots / videos if possible!
    Im too far gone in this that i don’t know how to make them converse
local PathfindingService = game:GetService("PathfindingService")
local debris = game:GetService("Debris")
local NPC = script.Parent
local Humanoid = script.Parent:FindFirstChild("Humanoid")
local HRP = NPC:FindFirstChild("HumanoidRootPart")
local points = NPC:FindFirstChild("Points")
points.Value = 0
local path = PathfindingService:CreatePath({
	AgentCanJump = true,
	AgentCanClimb = true,
	WaypointSpacing = 1,
	Agentheight = 0,
	AgentRadius = 3,
	Costs = {
		door1 = 0,
		door2 = 0,
	},
})

local animator = Humanoid:FindFirstChild("Animator")
local npcgoals = workspace.NPCgoals:GetChildren()

local function victorydance()
	local caligirl = Instance.new("Animation")
	caligirl.AnimationId = "rbxassetid://130982219069411"
	local caligirlanim = animator:LoadAnimation(caligirl)
	caligirlanim.Looped = true
	caligirlanim:Play()
	task.wait(5)
	caligirlanim:Stop()
end


local prevGoal = nil
local function chooseNewGoal()
	if #npcgoals == 1 then
		return npcgoals[1]
	end
	local newGoal
	repeat
		newGoal = npcgoals[math.floor(math.random(1, #npcgoals))]
	until newGoal ~= prevGoal
	return newGoal
end

local randomgoal = chooseNewGoal()



local function chatterbox()
	local minDistance = math.huge
	local closestNPC
	for _, npc in ipairs(script.Parent.Parent:GetChildren()) do
		local distance = (HRP.Position - npc.Position).Magnitude
		if distance < minDistance then
			minDistance = distance
			closestNPC = npc
		end
	Humanoid:MoveTo(npc.Position)
	end
	local function pathfind()
		local success, errorMessage = pcall(function()
			path:ComputeAsync(NPC.PrimaryPart.Position, randomgoal.Position)
		end)
		if success then
			for _, waypoint in pairs(path:GetWaypoints()) do
				local part = Instance.new("Part")
				part.Parent = game.Workspace
				part.Material = Enum.Material.Neon
				part.Anchored = true
				part.CanCollide = false
				part.Shape = Enum.PartType.Ball
				part.Position = waypoint.Position
				Humanoid:MoveTo(waypoint.Position)
				Humanoid.MoveToFinished:Wait()
				debris:AddItem(part, 1)
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					Humanoid.Jump = true
				end
			end
			points.Value += 1
			NPC.Head.BillboardGui.TextLabel.Text = "Points: " .. tostring(points.Value)
			print(points.Value)
			victorydance()
			prevGoal = randomgoal
			randomgoal = chooseNewGoal()
		else
			warn(errorMessage)
		end
	end
end
1 Like

Making a schematic like this might help you visualize what your NPC needs to do behind-the-scenes

im trying to control 2 npcs from one script

My recommendation still stands. Visualize what your states are, and go from there.

I rewrote the script but now it just lags the game

while task.wait(0) do
	for _, v in pairs(NPC) do
		print("e")
		local Humanoid = v:FindFirstChild("Humanoid")
		task.spawn(function()
			local success, errorMessage = pcall(function()
				path:ComputeAsync(v.PrimaryPart.Position, randomgoal.Position)
			end)
			if success then
				for _, waypoint in pairs(path:GetWaypoints()) do
					local part = Instance.new("Part")
					part.Parent = game.Workspace
					part.Material = Enum.Material.Neon
					part.Anchored = true
					part.CanCollide = false
					part.Shape = Enum.PartType.Ball
					part.Position = waypoint.Position
					Humanoid:MoveTo(waypoint.Position)
					Humanoid.MoveToFinished:Wait()
					debris:AddItem(part, 1)
					if waypoint.Action == Enum.PathWaypointAction.Jump then
						Humanoid.Jump = true
					end
					prevGoal = randomgoal
					randomgoal = chooseNewGoal()
				end
			end
		end)	
	end
end