Warning Beefy post
I've been looking at UristMcSparks' State Machine when developing my games NPCs, but have recently come to the problem of them simply "hanging".
After roughly 2 minutes all the npcs that were involved in any activity simply stop, as if they've crashed. I've been testing them and they all begin to stop working slowly one after the other, all at the condition check "CantShoot".
This is that Condition:
local CantShoot = StateMachine.NewCondition()
CantShoot.Name = "CantShoot"
CantShoot.Evaluate = function()
local Check = math.random(1,10)
if Check>=3 then
return true
end
return false
end
CantShoot.TransitionState = PursueState
I'm not sure if it is an issue with this condition, or if there is something else happening. Also, it appears to be checking a condition that also just doesn't apply to the state:
table.insert(ShootState.Conditions,Damaged)
table.insert(ShootState.Conditions,CantSee)
table.insert(ShootState.Conditions,CantShoot)
--table.insert(ShootState.Conditions,CanPunch)
table.insert(PursueState.Conditions,Damaged)
table.insert(PursueState.Conditions,CanShoot)
While in the pursue state, the CantShoot condition also appears in the debug. I've looked over the code, and there is no reason for that to occur. Is there something I'm missing? Here is UristMcSparks' State creator/switcher for reference.
local SMachine = {}
SMachine.new = function(Debug)
local StateMachine = {}
StateMachine.WaitTime = game:GetService('RunService').Stepped
StateMachine.CurrentState = nil
StateMachine.SwitchState = function(newState)
if StateMachine.CurrentState then
StateMachine.CurrentState.Stop()
end
StateMachine.CurrentState = newState
Debug.Action.Text = newState.Name
if newState then
newState.Start()
end
end
StateMachine.NewState = function()
local state = {}
state.Name = ""
state.Conditions = {}
state.isRunning = false
state.Action = function() end
state.Run = function()
state.isRunning = true
while state.isRunning do
--check conditions
--print(state.Name..": checking conditions")
for _, condition in pairs(state.Conditions) do
-- print("Checking " .. condition.Name)
Debug.Condition.Text = condition.Name
if condition.Evaluate() then
--print(condition.Name .. " is true. Switching states")
return StateMachine.SwitchState(condition.TransitionState)
end
end
--if no conditions satisfied, perform action
state.Action()
wait(StateMachine.WaitTime)
end
end
state.Init = function()
end
state.Start = function()
--print("Starting " .. state.Name)
state.Init()
local thread = coroutine.create(state.Run)
coroutine.resume(thread)
end
state.Stop = function()
--print("Stopping " .. state.Name)
state.isRunning = false
end
return state
end
StateMachine.NewCondition = function()
local condition = {}
condition.Name = ""
condition.Evaluate = function() print("replace me") return false end
condition.TransitionState = {}
return condition
end
return StateMachine
end
return SMachine

2 comments
Here is an example of the StateMachine in action.
https://www.roblox.com/games/412844121/NPC-State-Machine-Test