在《黑神话:悟空》这款游戏中,NPC(非玩家角色)的智能行为对于创造一个富有沉浸感的游戏世界至关重要。为了实现复杂的敌人行为模式,游戏开发团队采用了行为树作为NPC决策的核心架构。本文将详细介绍《黑神话:悟空》中NPC AI的设计原理,特别关注行为树的设计与实现。
行为树概述
行为树是一种用于实现复杂决策逻辑的结构化方式。它由一系列节点组成,每个节点代表一个任务或者一个决策点。节点之间通过分支和序列连接起来,形成一棵树状结构。行为树的基本节点类型包括:
- Action Node(动作节点):执行具体的动作。
- Condition Node(条件节点):检查某个条件是否满足。
- Composite Node(复合节点):组合多个子节点,例如Sequence(顺序)、Selector(选择器)等。
NPC AI行为树设计
1. 敌人行为树基础结构
在《黑神话:悟空》中,敌人的行为树通常包含以下部分:
- Root Node(根节点):所有行为树的起点。
- Selector Node(选择器节点):尝试按顺序执行子节点,直到有一个成功。
- Sequence Node(顺序节点):按顺序执行所有子节点,必须全部成功才能视为成功。
- Condition Node(条件节点):检查特定条件是否满足。
- Action Node(动作节点):执行具体的行为动作。
示例行为树结构
+-------------+
| Root Node |
+-----+-------+
|
v
+-------------+
| Selector |
+-----+-------+
| |
v v
+-------------+ +-------------+
| Sequence A | | Sequence B |
+-----+-------+ +-----+-------+
| | |
v v v
+-------------+ +-------------+ +-------------+
| Condition 1 | | Condition 2 | | Condition 3 |
+-----+-------+ +-----+-------+ +-----+-------+
| | | |
v v v v
+-------------+ +-------------+ +-------------+ +-------------+
| Action 1A | | Action 1B | | Action 2 | | Action 3 |
+-------------+ +-------------+ +-------------+ +-------------+
2. 具体节点实现
示例代码:Condition Node
class ConditionNode : public BehaviorTreeNode {
public:
virtual ~ConditionNode() {
}
virtual BehaviorStatus Execute(EnemyAI* enemy) override {
if (CheckCondition(enemy)) {
return BehaviorStatus::SUCCESS;
}
return BehaviorStatus::FAILURE;
}
private:
bool CheckCondition(EnemyAI* enemy) {
// 检查条件,例如敌人是否能看到玩家
return enemy->CanSeePlayer();
}
};
示例代码:Action Node
class ActionNode : public BehaviorTreeNode {
public:
virtual ~ActionNode() {
}
virtual BehaviorStatus Execute(EnemyAI* enemy) override {
// 执行具体动作,例如攻击玩家
enemy->Attack();
return BehaviorStatus::SUCCESS;
}
};
3. 实现复合节点
示例代码:Sequence Node
class SequenceNode : public BehaviorTreeNode {
public:
virtual ~SequenceNode() {
}
virtual BehaviorStatus Execute(EnemyAI* enemy) override {
for (auto& child : children) {
auto status = child->Execute(enemy);
if (status == BehaviorStatus::FAILURE) {
return BehaviorStatus::FAILURE;
} else if (status == BehaviorStatus::RUNNING) {
return BehaviorStatus::RUNNING;
}
}
return BehaviorStatus::SUCCESS;
}
};
示例代码:Selector Node
class SelectorNode : public BehaviorTreeNode {
public:
virtual ~SelectorNode() {
}
virtual BehaviorStatus Execute(EnemyAI* enemy) override {
for (auto& child : children) {
auto status = child->Execute(enemy);
if (status != BehaviorStatus::FAILURE) {
return status;
}
}
return BehaviorStatus::FAILURE;
}
};
4. 敌人行为树实例
假设我们有一个简单的敌人行为树,其目标是让敌人寻找并攻击玩家:
+-------------+
| Root Node |
+-----+-------+
|
v
+-------------+
| Selector |
+-----+-------+
| |
v v
+-------------+ +-------------+
| Sequence A | | Sequence B |
+-----+-------+ +-----+-------+
| | |
v v v
+-------------+ +-------------+ +-------------+
| CanSeePlayer| | IsHurt | | IsLowHealth|
+-----+-------+ +-----+-------+ +-----+-------+
| | | |
v v v v
+-------------+ +-------------+ +-------------+ +-------------+
| Attack | | Flee | | Heal | | Idle |
+-------------+ +-------------+ +-------------+ +-------------+
伪代码实现
// 假设这是敌人AI类的一部分
void EnemyAI::UpdateBehaviorTree() {
behaviorTree->Execute(this);
}
// 假设这是行为树的根节点
class EnemyBehaviorTree : public BehaviorTreeNode {
public:
virtual ~EnemyBehaviorTree() {
}
virtual BehaviorStatus Execute(EnemyAI* enemy) override {
// 选择器节点
auto selector = new SelectorNode();
// 序列节点A
auto sequenceA = new SequenceNode();
sequenceA->AddChild(new ConditionNode([](EnemyAI* e) {
return e->CanSeePlayer(); }));
sequenceA->AddChild(new ActionNode([](EnemyAI* e) {
e->Attack(); }));
// 序列节点B
auto sequenceB = new SequenceNode();
sequenceB->AddChild(new ConditionNode([](EnemyAI* e) {
return e->IsHurt(); }));
sequenceB->AddChild(new ActionNode([](EnemyAI* e) {
e->Flee(); }));
// 序列节点C
auto sequenceC = new SequenceNode();
sequenceC->AddChild(new ConditionNode([](EnemyAI* e) {
return e->IsLowHealth(); }));
sequenceC->AddChild(new ActionNode([](EnemyAI* e) {
e->Heal(); }));
// 序列节点D
auto sequenceD = new SequenceNode();
sequenceD->AddChild(new ActionNode([](EnemyAI* e) {
e->Idle(); }));
selector->AddChild(sequenceA);
selector->AddChild(sequenceB);
selector->AddChild(sequenceC);
selector->AddChild(sequenceD);
return selector->Execute(enemy);
}
};
结论
通过上述例子可以看出,《黑神话:悟空》中的NPC AI行为树不仅能够实现复杂的决策逻辑,而且还可以轻松地扩展和维护。行为树的设计让开发者能够清晰地组织和管理NPC的行为,从而创造出更加生动和互动的游戏体验。