行为树(Behavior Tree, BT)是一种用于控制复杂AI行为的模型,广泛应用于游戏中的NPC(非玩家角色)行为控制。行为树由节点组成,每个节点代表一个行为或决策。节点可以是复合节点(Composite)、装饰节点(Decorator)或叶子节点(Leaf)。
下面是一个用 Lua 编写的简单行为树算法示例。
行为树节点类
-- 定义行为树节点基类
BTNode = {}
BTNode.__index = BTNode
function BTNode:new(name)
local node = {
name = name
}
setmetatable(node, BTNode)
return node
end
function BTNode:run()
error("BTNode:run() should be overridden")
end
-- 定义复合节点类(顺序节点)
SequenceNode = setmetatable({}, {__index = BTNode})
SequenceNode.__index = SequenceNode
function SequenceNode:new(name)
local node = BTNode:new(name)
node.children = {}
setmetatable(node, SequenceNode)
return node
end
function SequenceNode:addChild(child)
table.insert(node.children, child)
end
function SequenceNode:run()
for _, child in ipairs(self.children) do
local status = child:run()
if status ~= "success" then
return status
end
end
return "success"
end
-- 定义复合节点类(选择节点)
SelectorNode = setmetatable({}, {__index = BTNode})
SelectorNode.__index = SelectorNode
function SelectorNode:new(name)
local node = BTNode:new(name)
node.children = {}
setmetatable(node, SelectorNode)
return node
end
function SelectorNode:addChild(child)
table.insert(node.children, child)
end
function SelectorNode:run()
for _, child in ipairs(self.children) do
local status = child:run()
if status ~= "failure" then
return status
end
end
return "failure"
end
-- 定义叶子节点类(行为节点)
ActionNode = setmetatable({}, {__index = BTNode})
ActionNode.__index = ActionNode
function ActionNode:new(name, action)
local node = BTNode:new(name)
node.action = action
setmetatable(node, ActionNode)
return node
end
function ActionNode:run()
return self.action()
end
-- 测试行为树算法
local function isEnemyVisible()
print("检查敌人是否可见")
return "success" -- 假设敌人可见
end
local function moveToEnemy()
print("移动到敌人位置")
return "success"
end
local function attackEnemy()
print("攻击敌人")
return "success"
end
local root = SelectorNode:new("Root")
local sequence = SequenceNode:new("Engage Enemy")
sequence:addChild(ActionNode:new("Is Enemy Visible", isEnemyVisible))
sequence:addChild(ActionNode:new("Move To Enemy", moveToEnemy))
sequence:addChild(ActionNode:new("Attack Enemy", attackEnemy))
root:addChild(sequence)
-- 运行行为树
root:run()
解释
- BTNode类:定义了行为树节点的基类,包含节点名称和一个虚拟的
run 方法。
- SequenceNode类:定义了顺序节点,继承自
BTNode 。顺序节点按顺序执行其子节点,直到一个子节点失败或所有子节点成功。
- SelectorNode类:定义了选择节点,继承自
BTNode 。选择节点按顺序执行其子节点,直到一个子节点成功或所有子节点失败。
- ActionNode类:定义了行为节点,继承自
BTNode 。行为节点执行具体的动作,并返回动作的结果。
- 测试代码:创建了一些行为节点和复合节点,并构建了一个简单的行为树。然后运行行为树,输出行为执行的过程。
输出
运行上述代码将输出以下内容:
检查敌人是否可见
移动到敌人位置
攻击敌人
这个简单的行为树算法可以根据实际需求进行扩展和优化,例如引入更多的节点类型、处理复杂的行为逻辑等。通过合理的行为树算法,可以有效控制游戏中的NPC行为,提升游戏的智能性和可玩性。 |