소개
이 모듈은 Cocos 프로젝트에서 전투 프레임워크를 사용하여 AI 구현에 적용한 내용입니다. 작성자 개인의 학습과 참고자료를 바탕으로 작성되었으며, 피드백과 수정사항이 있다면 언제든지 알려주시면 감사하겠습니다.
AI 모듈 개요
AI 모듈은 주로 NPC의 인공지능 행동을 제어하거나 자동 전투를 수행하는 데 사용됩니다. 구현 방법은 프로젝트 요구사항에 따라 달라지지만, 주로 **유한상태기(FSM - Finite State Machine)**와 **행동트리(Behavior Tree)**가 많이 사용됩니다.
유한상태기(FSM)
#####개념 설명
유한상태기는 시스템의 상태, 이벤트, 그리고 그에 따른 반응을 정의하는 프로그래밍 패러다임입니다. 세 가지 핵심 요소가 있습니다:
- 상태(State): 시스템이 현재 어떤 상태에 있는지 나타냅니다.
- 이벤트(Event): 시스템에 일어난 사건입니다.
- 반응(Response): 상태에서 이벤트가 발생했을 때 시스템이 어떻게 반응할지 정의합니다.
유한상태기의 주요 특징은 다음과 같습니다:
- 상태의 수는 유한합니다.
- 한 번에 하나의 상태만을 가지는 합니다.
- 특정 조건 하에 상태를 전환할 수 있습니다.
Cocos 예제
상태를 정의하는 인터페이스:
export interface IState {
OnEnter(): void; // 상태 진입 시 호출
OnExit(): void; // 상태 이탈 시 호출
OnUpdate(deltaTime: number): void; // 상태 유지 중 실행
}
상태 유형 열거체:
export enum StateType {
Inactive, // 비활성화
WaitingStart, // 게임 시작 대기
Idle, // 대기
Move, // 이동
Attack, // 공격
Killing, // 연속 공격
Die, // 죽음
MonsterCosplay, //몬스터 코즈플레이
GameEnd // 게임 종료
}
상태기 클래스:
@ccclass('StateController')
export class StateController {
private currentState: IState;
private states: Map<StateType, IState>;
private sharedData: SharedData;
constructor(sharedData: SharedData) {
this.states = new Map<StateType, IState>();
this.sharedData = sharedData;
}
addState(stateType: StateType, state: IState) {
if (!this.states.has(stateType)) {
this.states.set(stateType, state);
}
}
switchState(stateType: StateType) {
if (!this.states.has(stateType)) return;
const previousState = this.currentState;
if (previousState) {
previousState.OnExit();
}
this.currentState = this.states.get(stateType);
if (this.currentState) {
this.currentState.OnEnter();
}
}
update(deltaTime: number) {
this.currentState?.OnUpdate(deltaTime);
}
}
상태 제어 클래스:
@ccclass('Character')
export class Character extends BaseCharacter {
private stateController: StateController;
private sharedData: CharacterSharedData = new CharacterSharedData();
initializeStateController() {
this.stateController = new StateController(this.sharedData);
this.stateController.addState(StateType.WaitingStart, new WaitingState(this.stateController));
this.stateController.addState(StateType.Idle, new IdleState(this.stateController));
this.stateController.addState(StateType.Attack, new AttackState(this.stateController));
this.stateController.addState(StateType.Die, new DieState(this.stateController));
}
initialize() {
super.initialize();
this.initializeStateController();
this.stateController.switchState(StateType.WaitingStart);
}
}
대기 상태 예제:
class WaitingState implements IState {
private stateController: StateController;
private sharedData: CharacterSharedData;
constructor(stateController: StateController) {
this.stateController = stateController;
this.sharedData = stateController.sharedData as CharacterSharedData;
}
OnEnter() {
// 대기 상태 진입시의 초기화 로직
}
OnExit() {
// 대기 상태 이탈시의 정리 로직
}
OnUpdate(deltaTime: number) {
if (isGameStarted) {
this.stateController.switchState(StateType.Idle);
}
}
}
행동트리
#####개념 설명
행동트리는 복잡한 행동 로직을 그래픽화로 표현한 구조로, 게임 개발, 로봇 제어, 인공지능 분야에서 널리 사용됩니다. 주요 노드 유형은 다음과 같습니다:
- 액션 노드(Action Nodes): 특정 작업을 수행합니다. (예: 이동, 공격, 대기)
- 조건 노드(Conditional Nodes): 조건을 검사합니다.
- 컴포짓 노드(Composite Nodes): 다른 노드들의 실행 순서를 제어합니다. (순서 노드, 선택 노드)
- 데코레이터 노드(Decorator Nodes): 자식 노드의 행위를 수정합니다.
간단한 사용 예제
private behaviorType: number = 0;
public get BehaviorType(): number { return this.behaviorType; }
public set BehaviorType(value: number) {
switch (value) {
case 0:
case 9:
this.ChangeAnimation("idle", true);
break;
case 1:
case 3:
case 4:
this.ChangeAnimation("run", true);
break;
case 10:
this.ChangeAnimation("die", false);
break;
default:
Logger.Error("Character BehaviorType Error: " + value);
break;
}
this.behaviorType = value;
}
ChangeAnimation(aniName: string, isLoop: boolean, func?) {
// 애니메이션 제어 로직
}
참고 자료
- "유한상태기(FSM)의 설계 tư duy를 어떻게 깊이 이해할 수 있을까요?" -知乎
- "JavaScript와 유한상태기" -阮一峰의 웹 블로그