본문 바로가기
-----ETC-----/C++ 게임 개발 시리즈

[C++ 게임 개발 시리즈] Day 20: AI 행동 트리

by cogito21_cpp 2024. 8. 1.
반응형

AI 행동 트리

행동 트리(Behavior Tree)는 게임 AI에서 복잡한 행동을 정의하고 제어하기 위한 강력한 도구입니다. 상태 머신(State Machine)보다 더 유연하고 확장 가능한 구조를 제공합니다. 행동 트리는 계층적 구조를 가지며, 각 노드는 조건이나 행동을 나타냅니다.

행동 트리 기초

행동 트리는 세 가지 주요 노드 유형을 포함합니다:

  1. 선택자(Selector): 자식 노드 중 하나가 성공할 때까지 순차적으로 실행합니다.
  2. 시퀀스(Sequence): 모든 자식 노드가 성공해야 성공합니다. 하나라도 실패하면 실패합니다.
  3. 행동(Action): 실제 행동을 수행하는 노드입니다.

행동 트리 구현 예제

다음 예제에서는 간단한 행동 트리를 구현합니다. 여기서는 NPC가 목표를 찾고, 목표를 따라가며, 목표를 공격하는 간단한 시나리오를 구현합니다.

기본 노드 클래스 정의

#include <iostream>
#include <vector>
#include <functional>

enum class NodeStatus {
    Success,
    Failure,
    Running
};

class Node {
public:
    virtual ~Node() {}
    virtual NodeStatus tick() = 0;
};

class ActionNode : public Node {
public:
    ActionNode(std::function<NodeStatus()> action) : action(action) {}

    NodeStatus tick() override {
        return action();
    }

private:
    std::function<NodeStatus()> action;
};

선택자 노드 정의

class Selector : public Node {
public:
    void addChild(Node* child) {
        children.push_back(child);
    }

    NodeStatus tick() override {
        for (auto& child : children) {
            NodeStatus status = child->tick();
            if (status != NodeStatus::Failure) {
                return status;
            }
        }
        return NodeStatus::Failure;
    }

private:
    std::vector<Node*> children;
};

시퀀스 노드 정의

class Sequence : public Node {
public:
    void addChild(Node* child) {
        children.push_back(child);
    }

    NodeStatus tick() override {
        for (auto& child : children) {
            NodeStatus status = child->tick();
            if (status != NodeStatus::Success) {
                return status;
            }
        }
        return NodeStatus::Success;
    }

private:
    std::vector<Node*> children;
};

행동 트리 구현

다음은 간단한 행동 트리를 구현한 예제입니다.

NodeStatus findTarget() {
    std::cout << "Finding target..." << std::endl;
    return NodeStatus::Success; // 단순히 성공으로 가정
}

NodeStatus moveToTarget() {
    std::cout << "Moving to target..." << std::endl;
    return NodeStatus::Running; // 단순히 실행 중으로 가정
}

NodeStatus attackTarget() {
    std::cout << "Attacking target..." << std::endl;
    return NodeStatus::Success; // 단순히 성공으로 가정
}

int main() {
    // 행동 트리 생성
    Selector root;

    Sequence sequence;
    root.addChild(&sequence);

    ActionNode findTargetNode(findTarget);
    ActionNode moveToTargetNode(moveToTarget);
    ActionNode attackTargetNode(attackTarget);

    sequence.addChild(&findTargetNode);
    sequence.addChild(&moveToTargetNode);
    sequence.addChild(&attackTargetNode);

    // 행동 트리 실행
    while (root.tick() == NodeStatus::Running) {
        std::cout << "Behavior tree running..." << std::endl;
    }

    std::cout << "Behavior tree completed." << std::endl;
    return 0;
}

결론

오늘은 AI 행동 트리를 사용하여 NPC의 복잡한 행동을 구현하는 방법을 학습했습니다. 행동 트리는 상태 머신보다 더 유연하고 확장 가능한 구조를 제공하여 복잡한 AI를 구현할 수 있습니다. 질문이나 추가적인 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "Day 21: 적 캐릭터와 NPC의 AI 구현"에 대해 학습하겠습니다.

반응형