커스텀 데코레이터의 halt() 구현 (Custom Decorator’s halt() Implementation)
1. 개요
커스텀 데코레이터의 halt() 메서드는 데코레이터가 외부에서 중단될 때 호출되며, 내부 상태의 초기화와 자식 노드의 halt 전파를 담당한다. 올바른 halt 구현은 리소스 누수 방지, 상태 일관성 유지, 안전한 행동 중단의 핵심이다.
2. halt()의 기본 구현 패턴
void halt() override
{
// 1. 내부 상태 초기화
counter_ = 0;
timer_started_ = false;
cached_result_ = BT::NodeStatus::IDLE;
// 2. 기반 클래스의 halt() 호출 (자식 halt 포함)
DecoratorNode::halt();
}
2.1 기반 클래스의 halt() 동작
DecoratorNode::halt()는 다음을 수행한다.
haltChild()호출: 자식이RUNNING상태이면 자식의halt()호출setStatus(NodeStatus::IDLE): 자신의 상태를IDLE로 전환
3. halt() 호출 시점
| 시점 | 원인 |
|---|---|
| ReactiveSequence에서 조건 실패 | 앞쪽 조건이 FAILURE → 뒤쪽 노드 halt |
| Timeout 만료 | 시간 초과 → 자식 halt |
| 행동 트리 중지 | tree.haltTree() 호출 |
| 상위 노드의 halt 전파 | 상위가 halt되면 자식도 halt |
4. 내부 상태 초기화의 필수성
halt 후 데코레이터가 다시 tick되면 처음부터 실행을 시작하여야 한다. 내부 상태가 초기화되지 않으면 이전 실행의 잔여 상태가 영향을 미친다.
4.1 초기화가 필요한 상태 변수 유형
| 상태 변수 | 예시 | 초기화 값 |
|---|---|---|
| 카운터 | retry_count_, repeat_count_ | 0 |
| 타이머 | start_time_ | 리셋 |
| 플래그 | timer_started_, already_completed_ | false |
| 캐시 | cached_result_ | IDLE |
5. halt()가 불필요한 경우
무상태(stateless) 데코레이터(Inverter, ForceSuccess, ForceFailure)는 내부 상태가 없으므로, halt()를 오버라이드할 필요가 없다. 기반 클래스의 기본 halt()가 자식 halt만 처리하면 충분하다.
6. 비차단 halt의 원칙
halt() 메서드는 가능한 한 신속하게 완료되어야 한다. halt() 내부에서 긴 대기나 차단 호출이 발생하면 행동 트리의 tick이 지연된다.
7. 참고 문헌
- BehaviorTree.CPP 공식 문서. https://www.behaviortree.dev/
| 버전 | 날짜 | 변경 사항 |
|---|---|---|
| v0.1 | 2026-04-05 | 초안 작성 |