Defold 寻路与 AI:寻路算法、导航网格与行为树实战

系统覆盖 Defold 游戏 AI:A* 寻路与导航网格(Navmesh)、路径平滑、敌人追逐与巡逻、有限状态机 AI、行为树(BT)决策、视线检测与简单群体行为,含 Lua 实战代码。

引言

游戏 AI = 「决策 + 移动」。决策层用状态机/行为树决定「下一步干什么」,移动层用寻路算法决定「怎么走到那」。本文把 Defold 游戏 AI 讲透:先讲 A* 寻路原理与在 Lua 里的实现,再讲导航网格(Navmesh)与路径平滑,接着覆盖敌人 AI 的典型模式(追逐、巡逻、视线检测),再给行为树(BT)与状态机的选择与实战,最后讲群体行为与性能优化,让你给 Defold 敌人配上会「思考」的脑子。

前置:/defold-game-engine-complex-logic-state-management/(状态机)、/defold-script-system-lua/(协程与消息)、/defold-physics-collision/(碰撞检测)。Lua 语言见 [[lua]]。


目录


1. AI 分层:决策与移动

游戏 AI 拆成两层,各司其职:

决策层(脑子):
  状态机 / 行为树 → 决定「下一步做什么」
        ↓ 下达目标
移动层(腿):
  寻路算法 → 从 A 点到 B 点的路径
  平滑/避让 → 走起来自然

典型 AI 循环:

每帧:
  1. 感知(视野/距离/血量)
  2. 决策(打/追/跑/待机)
  3. 移动(朝目标走/用寻路)
层工具问题
决策FSM / 行为树干什么
移动A*/Navmesh怎么走
感知距离/射线/视野知道啥

心智:AI = 感知 → 决策 → 移动 的循环——别一上来写复杂算法,先分层想清楚。


2. A* 寻路算法原理

A = Dijkstra + 启发式*——用「已走成本 g + 估算成本 h」引导搜索:

f(n) = g(n) + h(n)
g(n) = 起点到 n 的实际成本
h(n) = n 到终点的估算成本(启发式,如曼哈顿距离)

开放列表:待考察节点(按 f 排序,取最小)
关闭列表:已考察节点
过程:从起点出发,扩展邻居,选 f 最小的继续,直到终点

启发式选择:

地图h 启发式
四方向网格曼哈顿距离
八方向网格切比雪夫距离
任意图欧氏距离

为什么 A 快*:启发式把搜索「引向终点」,不用盲搜整张地图。

记忆:A 的核心是 f = g + h*——h 引导方向、g 保证最优,地图越大越省事。


3. Lua 实现 A*:网格寻路实战

网格寻路的 Lua 实现(简化):

-- 网格:1=可通过,0=障碍
local GRID = {
    {1,1,1,1,1,1},
    {1,0,0,0,1,1},
    {1,1,1,0,1,1},
    {1,0,1,1,1,1},
}

local DIRS = { {1,0},{-1,0},{0,1},{0,-1} }   -- 四方向

local function heuristic(a, b)
    return math.abs(a.x - b.x) + math.abs(a.y - b.y)   -- 曼哈顿
end

-- 返回从 start 到 goal 的路径(节点列表)
local function astar(grid, start, goal)
    local open, closed = { [start] = { g=0, f=heuristic(start, goal), from=nil } }, {}
    while next(open) do
        -- 取 f 最小的节点
        local cur, curf = nil, math.huge
        for node, data in pairs(open) do
            if data.f < curf then cur, curf = node, data.f end
        end
        if cur.x == goal.x and cur.y == goal.y then
            -- 回溯路径
            local path = {}
            local n = cur
            while n do path[#path+1] = n; n = open[n].from end
            return path
        end
        open[cur] = nil; closed[cur] = true
        for _, d in ipairs(DIRS) do
            local nx, ny = cur.x+d[1], cur.y+d[2]
            if grid[ny] and grid[ny][nx] == 1 and not closed[{x=nx,y=ny}] then
                local ng = (open[cur].g or 0) + 1
                local key = { x=nx, y=ny }
                if not open[key] or ng < open[key].g then
                    open[key] = { g=ng, f=ng+heuristic(key, goal), from=cur }
                end
            end
        end
    end
    return nil   -- 无路可达
end

在游戏里用:

-- 敌人寻路到玩家
local path = astar(GRID, {x=ex, y=ey}, {x=px, y=py})
if path then
    -- 沿路径逐节点移动
    self.path = path; self.path_idx = 1
end

记忆:A Lua 实现约 30 行*——开放表取最小 f、扩展邻居、回溯路径,够游戏用;要更高效可换二叉堆。


4. 导航网格(Navmesh)与路径平滑

网格寻路局限:障碍形状复杂时网格粒度粗、路径锯齿。Navmesh(导航网格)更优:

Navmesh:把可行走区域多边形化 → 多边形凸块
寻路在凸多边形之间跑 → 路径更平滑、更高效

Defold 里做 Navmesh 的常见做法:

1. 手工铺设:把地形划分成凸多边形,存到 Lua 表
2. 工具生成:外部工具导出 navmesh 数据(JSON)→ Defold 加载
3. 简化:小型 2D 游戏用「网格 + 路径平滑」足够

路径平滑(消除锯齿走位):

-- 简单平滑:直线可达就跳过中间节点(视线剪枝)
local function smooth(self, path)
    local result = {}
    for i = 1, #path do
        local cur = path[i]
        if not self.prev or not line_of_sight(self.prev, cur) then
            result[#result+1] = cur
            self.prev = cur
        end
    end
    return result
end
方案适用平滑度
网格 A*小型/格子地图锯齿
网格 + 平滑常见 2D较好
Navmesh复杂地形最好

记忆:小地图网格 + 平滑够用,复杂地形上 Navmesh——「直线可达就跳点」的剪枝平滑最实用。


5. 敌人 AI:追逐、巡逻与视线检测

追逐(简单跟随):

-- 朝玩家移动
local player = self.player_pos
local dir = vmath.normalize(player - go.get_position("."))
go.set_velocity("." , dir * self.speed)   -- 或手动位移

巡逻(来回走 + 边界回退):

-- 巡逻点列表
self.patrol = { vmath.vector3(10,0,0), vmath.vector3(60,0,0) }
self.patrol_idx = 1

local function update_patrol(self)
    local target = self.patrol[self.patrol_idx]
    local pos = go.get_position(".")
    local dist = vmath.length(target - pos)
    if dist < 5 then   -- 到达 → 换下一个点
        self.patrol_idx = (self.patrol_idx % #self.patrol) + 1
    else
        local dir = vmath.normalize(target - pos)
        go.set_position("." , pos + dir * self.speed * dt)
    end
end

视线检测(能看到才追):

-- 距离 + 角度 + 射线遮挡
local function has_line_of_sight(self, from, to)
    local dist = vmath.length(to - from)
    if dist > self.view_range then return false end          -- 超出视野
    local hit = physics.raycast(from, to)                     -- 射线
    return not hit or hit.distance > dist                     -- 无遮挡
end

记忆:追逐 = 朝目标走;巡逻 = 点列表循环;视线 = 距离 + 射线遮挡——三个模式拼出有压迫感的敌人。


6. 有限状态机 AI:三态敌人实战

状态机 AI(IDLE → CHASE → ATTACK):

local STATE = { IDLE=1, CHASE=2, ATTACK=3 }

function init(self)
    self.state = STATE.IDLE
    self.range = 200      -- 警觉距离
    self.attack_range = 40
    self.attack_cd = 0
end

function update(self, dt)
    local player = self.player_pos
    local pos = go.get_position(".")
    local dist = vmath.length(player - pos)

    -- 状态转移
    if dist < self.range and self.state ~= STATE.CHASE then
        set_state(self, STATE.CHASE)
    elseif dist < self.attack_range and self.state ~= STATE.ATTACK then
        set_state(self, STATE.ATTACK)
    elseif dist > self.range and self.state == STATE.CHASE then
        set_state(self, STATE.IDLE)
    end

    -- 状态行为
    if self.state == STATE.CHASE then
        chase_player(self, dt)          -- 追逐
    elseif self.state == STATE.ATTACK then
        attack_player(self, dt)         -- 攻击 + 冷却
    end
end

状态机优点:直观、易调参、好排错——适合状态少、转换清晰的 AI。

记忆:FSM AI 三步——定义状态、判距离转移、按状态执行——状态少时最清晰,别为小 AI 硬上行为树。


7. 行为树(BT):更复杂的决策

行为树把决策组织成树——节点返回 成功/失败/运行:

       选择器(Sequence 全成 / Selector 任一)
        └─ 条件:玩家在视野?
        └─ 序列:
             ├─ 行动:追击
             ├─ 条件:距离 < 攻击距离?
             └─ 行动:攻击

Defold 里简单实现行为树节点:

-- 行为节点:返回 "success" / "fail" / "running"
local function node_chase(self, ctx)
    if not ctx.target then return "fail" end
    chase_player(self, ctx.dt)
    return vmath.length(ctx.target - go.get_position(".")) > 40 and "running" or "success"
end

local function node_attack(self, ctx)
    if vmath.length(ctx.target - go.get_position(".")) > 40 then return "fail" end
    attack_player(self)
    return "running"
end

-- 选择器:依次尝试,成功即返回
local function selector(...)
    return function(self, ctx)
        for _, n in ipairs({...}) do
            local r = n(self, ctx)
            if r ~= "fail" then return r end
        end
        return "fail"
    end
end

FSM vs 行为树:

维度FSM行为树
状态清晰度高树形
扩展性状态多会乱加节点即可
复用低节点可复用
适合简单 AI复杂/组合行为

记忆:状态多、行为能组合 → 行为树;状态少 → FSM 够用——别拿锤子砸钉子,也别为复杂硬上简单。


8. 群体行为:编队与避让

**群体 AI(敌人波、守卫队)**的经典做法:

避让(分离)——别挤成一团:

-- 对每个邻居施加斥力
local function separation(self)
    local push = vmath.vector3(0, 0, 0)
    for _, other in ipairs(self.nearby) do
        local delta = go.get_position(".") - other.pos
        local d = vmath.length(delta)
        if d < self.min_sep and d > 0.01 then
            push = push + vmath.normalize(delta) / d   -- 距离越近斥力越大
        end
    end
    return push * self.sep_strength
end

编队(队列)——跟随队长:

-- 士兵跟随队长,保持队形偏移
local function follow_leader(self, leader_pos, offset)
    local target = leader_pos + offset
    local dir = vmath.normalize(target - go.get_position("."))
    go.set_position(".", go.get_position(".") + dir * self.speed * dt)
end

记忆:群体 AI 两条力——分离斥力防拥挤、编队偏移保队形——简单公式就能模拟出「整齐军队」。


9. AI 性能优化

AI 是 CPU 大头——数量多必须优化:

优化做法效果
分帧每帧只更新部分 AI均摊开销
距离剔除远处 AI 降频/不更新省大头
简化感知定时射线段,别每帧省射线
预计算路径路径缓存复用省 A*
协程用协程做延迟决策分散开销

分帧示例:

-- 每帧只更新 1/3 的敌人(轮流)
function update(self, dt)
    local i = self.frame % 3
    for j = i, #self.enemies, 3 do
        update_enemy_ai(self.enemies[j], dt)
    end
    self.frame = self.frame + 1
end

记忆:AI 优化三板斧——分帧、距离剔除、路径缓存——几百个敌人也能流畅跑。


10. 速查表

需求做法
找路径A*(f=g+h)网格寻路
平滑路径视线剪枝(直线可达跳点)
复杂地形Navmesh 多边形导航
追逐朝目标 normalize 移动
巡逻巡逻点列表循环
视野距离 + 射线遮挡
决策FSM(状态少)/ 行为树(组合多)
避让邻居斥力 separation
编队队长偏移跟随
优化分帧 + 距离剔除 + 路径缓存

一句话记忆:Defold AI = 决策(FSM/行为树)+ 移动(A/Navmesh);A 用 f=g+h 网格寻路、直线可达就平滑剪枝;追逐朝目标、巡逻走点列表、视野看距离加射线;状态少用 FSM、行为组合上行为树;群体靠分离斥力 + 编队偏移;性能用分帧 + 剔除 + 路径缓存——给敌人装上会思考的脑子。**


延伸阅读

  • /defold-game-engine-complex-logic-state-management/ — 状态机与 AI 行为基础
  • /defold-physics-collision/ — 射线检测与碰撞
  • /defold-script-system-lua/ — 协程与消息驱动
  • /defold-performance-optimization/ — AI 性能优化
  • [[lua]] — Lua 语言深入
  • [[game]] — 游戏 AI 方法论

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「defold」更多文章

  1. Defold 音频系统:Sound 组件、背景音乐、3D 音效与声音管理
  2. Defold 精灵与动画:Sprite、Flipbook、缓动与程序动画
  3. Defold 着色器与后处理:GLSL 材质、特效与全屏后期