Type: concept
Confidence: 0.83
Created: 2026-04-16
Updated: 2026-04-16
Tags: 技术Lua游戏开发设计模式Lua编程

Lua 状态机

概述

Lua 状态机(HSM/FSM)将游戏逻辑拆分为离散状态,每个状态定义 enter/update/exit 回调;层次状态机(HSM)支持状态嵌套,子状态未处理的事件上浮父状态。

关键内容

基础有限状态机(FSM)

local StateMachine = {}
StateMachine.__index = StateMachine

function StateMachine.new(owner)
    return setmetatable({owner = owner, current = nil, states = {}}, StateMachine)
end

function StateMachine:add(name, state)
    -- state = {enter=fn, update=fn, exit=fn, transitions={event=nextName}}
    self.states[name] = state
end

function StateMachine:change(name, ...)
    if self.current and self.current.exit then
        self.current.exit(self.owner)
    end
    self.current = self.states[name]
    if self.current and self.current.enter then
        self.current.enter(self.owner, ...)
    end
end

function StateMachine:update(dt)
    if self.current and self.current.update then
        self.current.update(self.owner, dt)
    end
end

function StateMachine:handle(event, ...)
    if not self.current then return end
    local next = self.current.transitions and self.current.transitions[event]
    if next then
        self:change(next, ...)
        return true
    end
    return false
end

使用示例:敌人 AI

local enemy = {hp = 100}
local sm = StateMachine.new(enemy)

sm:add("idle", {
    enter = function(e) e.timer = 0 end,
    update = function(e, dt)
        e.timer = e.timer + dt
        if e.timer > 2 then sm:handle("patrol") end
    end,
    transitions = {patrol = "patrol", attack = "attack"},
})

sm:add("patrol", {
    update = function(e, dt) -- 巡逻逻辑  end,
    transitions = {attack = "attack", idle = "idle"},
})

sm:change("idle")  -- 初始化

-- 游戏主循环
sm:update(dt)
sm:handle("attack")  -- 外部事件触发状态转换

层次状态机(HSM)扩展

HSM 核心思想:状态可以有父状态。子状态 handle(event) 返回 false 时,事件向上冒泡到父状态处理。适合共享行为(如所有"移动中"状态共享"碰墙停止"逻辑)。

-- 在 handle 中加入父状态回退
function StateMachine:handle(event, ...)
    local state = self.current
    while state do
        local next = state.transitions and state.transitions[event]
        if next then
            self:change(next, ...)
            return true
        end
        state = state.parent  -- 上浮
    end
    return false
end

与事件总线集成

状态机 handle() 可直接连接 EventBus 事件,实现解耦触发:

EventBus.on("enemy_spotted", function(enemy)
    enemy.sm:handle("attack", enemy)
end)

设计建议

常见陷阱

来源

相关