[Unity] BT에 대해 알아보자

ChangBeom·2026년 1월 30일

Unity

목록 보기
19/20
post-thumbnail

게임 AI를 구현하다 보면 이런 순간이 온다.

"적이 상황에 맞게 행동했으면 좋겠는데... 상황이 많아질수록 코드가 지옥이 되네?"

처음에는 if문 몇 개로 시작했던 로직이
어느 순간 거대한 if문 덩어리가 되고
조금만 수정해도 다른 행동이 망가지는 상황이 생긴다.

이 문제를 해결하기 위해 게임 AI 분야에서 오래전부터 사용되어 온 구조가 바로
BT(Behavior Tree, 행동트리)이다.


[1.BT란 무엇인가?]

행동 트리는
AI의 의사결정을 "트리 구조"로 표현하는 방식이다.

코드를 위에서 아래로 쭉 실행하는 것이 아니라,

"어떤 행동을 할지 판단하는 구조"를 데이터처럼 구성하는 것

에 가깝다.

BT는 보통 다음과 같은 형태를 가진다.

          [Selector]
           /      \
     [Attack]   [Patrol]

AI는 트리를 위에서 아래로 탐색하며
지금 실행 가능한 행동을 찾아 수행한다.

즉, BT는

"어떤 행동을 할지 고르는 구조" + "행동 실행 시스템"

이 합쳐진 개념이라고 할 수 있다.


[2. 왜 BT를 쓰는가? (FSM과의 차이)]

AI 구조로 자주 비교되는 게 BT와 FSM(Finite State Machine, 유한 상태 머신)이다.

FSM은 이런 느낌이다.

Idle -> Chase -> Attack -> Dead

상태가 명확하고 단순할 때는 FSM이 좋다.
하지만 문제가 생기는 순간은 바로 여기다.

  • 상태가 많아질수록 전이 조건 폭발
  • 한 상태에서 여러 상황을 동시에 고려하기 어려움
  • 새로운 행동 추가 시 기존 로직 대규모 수정 필요

FSM은 "현재 상태" 중심 사고이고,
BT는 "지금 할 수 있는 행동" 중심 사고이다.

BT는 상태를 계속 바꾸는 대신,

매 프레임 트리를 다시 탐색하며, 상황에 맞는 행동을 선택한다.

그래서 구조가 훨씬 유연해진다.


[3. BT의 기본 구성 요소]

BT는 몇 가지 노드 타입으로 구성된다.

1) Composite 노드 (흐름 제어)

  • Selector (선택자)
    자식 노드를 왼쪽부터 실행하다가
    성공(Success)하거나 실행 중(Running) 상태가 나오면 그 노드에서 탐색을 멈춘다.
    AI 의사결정의 핵심 역할

  • Sequence (순차 실행)
    자식 노드를 순서대로 실행하며
    하나라도 실패하면 전체 실패
    행동 절차를 표현할 때 사용


2) Leaf 노드 (실제 행동)

  • Action 노드
    실제 행동을 수행한다.
    이동, 공격, 스킬 사용 등

  • Condition 노드
    조건을 검사한다.
    적이 사거리 안에 있는가?, 체력이 30% 이하인가?, 플레이어가 보이는가? 등
    조건은 행동을 실행할지 말지 결정하는 필터 역할을 한다.


[4. BT의 핵심 개념 - "Tick"]

BT는 보통 매 프레임 실행된다.
이 실행 단위를 Tick이라고 부른다.

void Update()
{
	behaviorTree.Tick();
}

Tick이 호출되면 트리는 루트부터 탐색을 시작하고
현재 실행 가능한 행동을 찾아 내려간다.

여기서 중요한 특징이 나온다.

BT는 기본적으로 매 Tick마다 다시 판단하지만,
Running 상태의 노드는 실행 흐름을 유지하기도 한다.

그래서 상황이 바뀌면
AI 행동도 자연스럽게 바뀐다.


[5. Unity에서 BT를 사용하는 이유]

Unity에서 AI를 만들 때 자주 겪는 문제들은 다음과 같다.

  • Update에 if문이 계속 늘어남
  • 애니메이션, 이동, 공격 로직이 서로 얽힘
  • 적 하나 추가할 때마다 코드 복붙

BT를 쓰면 구조가 이렇게 바뀐다.

기존 방식BT 방식
코드 중심구조(트리) 중심
상태 전이 관리행동 선택 구조
수정 시 코드 대공사노드 추가/교체

특히 Unity와 BT의 궁합이 좋은 이유는

컴포넌트 기반 구조 + 데이터 기반 AI 설계
가 잘 맞기 때문이다.

행동을 MonoBehaviour로 만들거나
ScriptableObject 기반 노드로 구성하면
디자이너 친화적인 AI 구조도 만들 수 있다.


[6. Unity에서의 기본적인 BT 활용 구조]

보통 이런 형태로 구성된다.

1) 기본 노드 정의

public abstract class BTNode
{
	public abstract NodeState Tick();
}

public enum NodeState
{
	Success,
    Failure,
    Running
}

2) Composite 노드 (예: Selector)

using System.Collections.Generic;

public class SelectorNode : BTNode
{
	private List<BTNode> _children;
    
    public SelectorNode(List<BTNode> children)
    {
    	_children = children;
    }
    
    public override NodeState Tick()
    {
    	foreach (var child in _children)
        {
        	var result = child.Tick();
            
            if(result == NodeState.Success)
            {
            	return NodeState.Success;
            }
            
            if(result == NodeState.Running)
            {
            	return NodeState.Running;
            }
        }
        
        return NodeState.Failure;
    }
}
                 

3) Action 노드 예시

public class MoveToTargetNode : BTNode
{
	private Transform _owner;
    private Transform _target;
    
    public MoveToTargetNode(Transform owner, Transform target)
    {
    	_owner = owner;
        _target = target;
    }
    
    public override NodeState Tick()
    {
    	float dist = Vector3.Distance(_owner.position, _target.position);
        
        if(dist < 1f)
       	{
        	return NodeState.Success;
        }
        
        _owner.position = Vector3.MoveTowards(
        	_owner.position,
            _target.position,
            Time.deltaTime * 3f);
            
        return NodeState.Running;
    }
}
  • 해당 예제는 이해를 돕기 위해 Transform을 직접 이동시키는 방식을 사용했지만
    실제 게임 로직에서는 NavMeshAgent 같은 내비게이션 시스템을 사용해 이동을 처리하며
    BT 노드는 실제 이동을 직접 처리하기보다는
    "이동을 시작하라"는 명령을 내리는 역할에 가깝게 구성되는 경우가 많다.

4) 트리 실행

public class EnemyAI : MonoBehaviour
{	
	public Transform target;

	private BTNode _root;
    
    void Start()
    {
    	_root = BuildTree();
    }
    
    void Update()
    {
    	_root.Tick();
    }
    
    private BTNode BuildTree()
    {
    	var moveToTarget = new MoveToTargetNode(transform, target);
        
        var root = new SelectorNode(new List<BTNode>
        {
        	moveToTarget
        });
        
        return root;
    }
}

이런식으로 만들면
AI로직이 Update에서 사라지고, 트리 구조로 분리된다.


[7. BT가 잘 어울리는 AI 유형]

BT는 특히 이런 AI에 강하다.

  • 몬스터 AI
  • NPC 행동 패턴
  • 보스 패턴 설계
  • 생존 / 탐색 / 전투 같은 복합 행동

즉,

"상황에 따라 행동이 유동적으로 바뀌어야 하는 AI"

에 매우 잘 맞는다.


[8. 정리]

행동 트리는 단순한 AI 구현 기법이 아니다.

  • 상태를 직접 관리하는 대신
  • 행동 선택 구조를 설계하는 방식으로 사고를 바꾸는 것

이다.

FSM이 "현재 나는 어떤 상태인가?"라면
BT는 "지금 무엇을 하는 게 가장 적절한가?"이다.

Unity에서 AI가 복잡해지기 시작했다면,
BT는 선택이 아니라 구조 개선 단계에서 반드시 만나게 되는 도구에 가깝다.


다음 글에선 간단하게라도 직접 BT를 활용하여 AI를 구현해보려고한다.

0개의 댓글