공부/Unreal

24.08.27

월러비 2024. 8. 28. 19:13

AI

BehaviorTree 생성

  • BehaviorTree 변수 선언은 Enemy 파생에서 선언하고, 트리의 사용은 Controller에서 Enemy에 있는 BehaviorTree 가 담긴 변수를 가져와서 사용하게 된다.
    • 즉, BehaviorTree는 AIController 클래스에서 실행된다.
  • Controller와 Enemy는 1대1 관계이다.
  • CEnemy_AI
    • 헤더 파일 - BehaviorTree 클래스 포인터 변수인 ‘비헤이비어 트리’ 선언 - BehaviorTree 포인터 자료형의 ‘비헤이비어 트리 가져오기’ 함수를 선언하고 ‘비헤이비어 트리’ 변수를 반환하는것으로 정의한다.
    //header
    UPROPERTY(EditDefaultsOnly, Category = "Team")
    		class UBehaviorTree* BehaviorTree; //비헤이비어 트리 저장
    
    • CPP 파일 - 생성자 함수 확인 - ‘에셋 가져오기’ 함수를 ‘BehaviorTree’ 로 지정하고 생성한 ‘BT_Melee’ 에셋의 레퍼런스 주소를 복사해서 불러온다. (기본값 지정)
    //CPP
    CHelpers::CreateActorComponent<UCAIBehaviorComponent>(this, &Behavior, "Behavior");
    
  • CAIController
    • CPP 파일 - ‘빙의 활성’ 함수 확인 - AIController에 있는 ‘비헤이비어 트리 실행’ 함수에 ‘적의 비헤이비어 트리 가져오기 함수 호출’을 넣고 호출한다.
    //CPP
    RunBehaviorTree(Enemy->GetBehaviorTree()); //트리 실행
    
  • BT_Melee
    • 생성 : 콘텐트 - 인공지능 - BehaviorTree
    • 루트 - Sequence 검색 후 연결 - Wait 검색 후 Sequence 노드와 연결

블랙보드 연결 설정

  • BB_Melee
    • 키는 필요하다면 ‘오브젝트’를 상속받아서 생성해야한다.
      • 주의 사항 : 블랙보드 디테일 - 키타입 - 베이스 클래스 : Object로 지정되어있다면 키에 값을 넣지 못하게 된다.
        • 해결 방법 : 오브젝트에 넣을 값의 자료형으로 이곳에서 변경해줘야한다.
          • 지금은 Character 자료형 사용
    • 생성 : 콘텐츠 - 인공지능 - 블랙보드
    • 새 키 - 오브젝트 형 선택 후 이름 변경 : Target - 키 타입 - 베이스 클래스 : Character

블랙보드 매 프레임 감지 호출 함수

  • CAIController
    • 감지 업데이트 활성 함수의 매개변수인 ‘동적 배열 포인터 주소’는 값이 이전에도 감지된 객체들이 ‘누적’되어서 들어온다.
      • 그래서, 매개변수를 쓰지는 않고, 현재 순간에 감지된 엑터들 리스트를 사용한다.
    • 헤더 파일 - BeginPlay 재정의 선언 - 델리게이트 함수인 ‘감지 업데이트 활성’ 함수에 ‘엑터 포인터 동적배열 주소 자료형을 넣고 선언한다.
    //header
    private:
    	//매 프레임 감지 델리게이트
    	UFUNCTION()
    		void OnPerceptionUpdated(const TArray<AActor*>& UpdatedActors);
    
    protected:
    	virtual void BeginPlay() override;
    
    • CPP 파일 - BeginPlay 정의 - ‘감지’ 변수의 ‘감지 업데이트 활성’ 함수의 ‘함수 연결’에 ‘연결할 함수가 있는 클래스, 연결할 함수’를 넣고 호출한다. - ‘감지 업데이트 활성’ 함수 정의 - ‘엑터들’ 동적 배열 변수 선언 - ‘감지’의 ‘현재 감지된 엑터들 가져오기’ 함수에 ‘감지 구분 : 모든 감지 가져오기 , 감지된 엑터들 ; 엑터들’을 넣고 호한다. - 감지된 엑터 확인 테스트
    //CPP
    //비헤비어 컴포넌트 가져오기
    Behavior = CHelpers::GetComponent<UCAIBehaviorComponent>(Enemy);
    
    void ACAIController::OnPerceptionUpdated(const TArray<AActor*>& UpdatedActors)
    {
    	//GetCurrentlyPerceivedActors : 현재 감지되어있는 엑터들 배열 반환 함수
    	//nullptr : 어느걸로 감지되었든 전부 받는다.
    	TArray<AActor*> actors; //감지된 엑터들 저장
    	Perception->GetCurrentlyPerceivedActors(nullptr, actors);
    
    	for (AActor* actor : actors)
    	{
    		CLog::Print(actor->GetName());
    	}
    }
    

블랙보드 키에 값 할당

  • AIController 클래스에는 ‘블랙 보드 컴포넌트’ 오브젝트 변수가 이미 선언되어있다.
    • 다만, 초기화가 되어있지 않다.
  • ObjectPtr : 오브젝트 자료형 포인터를 의미한다.
    • TObjectPtr<T>* : 스마트 포인터
    • 나중에 언리얼 취업을 진지하게 생각한다면 반드시 ‘스마트 포인터’ 찾아서 정리해라
    • 사용법은 포인터와 똑같다.
      • 포인터를 세부적으로 나눠놓은것이다.
      • 자동으로 제거되는 포인터들, 메모리들을 관리하기 위해 사용한다.
  • CHelpers
    • ‘엑터 컴포넌트 생성 함수’ 복사 - 매개변수의 T**를 TObjectPtr<T>*로 변경
  • CAIController
    • CPP 파일 - 생성자 함수 확인 - 부모 함수에 있는 블랙보드 변수에 ‘엑터 컴포넌트 생성’ 함수 호출하고 저장하기 - ‘빙의 활성’ 함수 확인 - ‘적’의 ‘비헤이비어 트리 가져오기’ 함수 호출 후 비어있는지 확인한다. - ‘AI컨트롤의 블랙보드’의 ‘가져오기’ 함수를 호출하여 가져온 ‘블랙보드의 주소’를 블랙보드 컴포넌트의 ‘블랙보드’ 변수를 선언하고 저장한다. - ‘블랙보드 사용’ 함수에 ‘적의 비헤이비어 트기 가져오기 함수 호출의 블랙보드 에셋 , 블랙보드’를 넣고 호출한다. - ‘감지 업데이트 활성’ 함수 확인 - ‘엑터들’의 ‘요소 반환하기’ 함수의 결과가 0보다 크다면 : ‘블랙보드’의 ‘오브젝트 값 설정’ 함수에 (값을 설정할 키 이름, 세팅할 값 : 감지된 엑터들 중 첫번쨰 값)을 넣고 호출한다. , 반환한다. - ‘블랙보드’의 ‘오브젝트 값 설정’ 함수에 (값을 설정할 키 이름, 세팅할 값 : Null)을 넣고 호출한다.
    //CPP
    //Blackboard는 AIController 클래스 내부에 이미 선언되어있는 UBlackboardComponent 변수다.
    CHelpers::CreateActorComponent<UBlackboardComponent>(this, &Blackboard, "Blackboard");
    
    void ACAIController::OnPossess(APawn* InPawn)
    {
    	Super::OnPossess(InPawn);
    
    	//폰에 빙의될거다.
    	Enemy = Cast<ACEnemy_AI>(InPawn);
    	SetGenericTeamId(Enemy->GetTeamID());
    
    	//트리 없으면 실행 안한다.
    	CheckNull(Enemy->GetBehaviorTree());
    
    	//블랙보드 사용한다고 알린다.
    	UBlackboardComponent* blackboard = Blackboard.Get(); //블랙보드 '주소' 가져오기
    	UseBlackboard(Enemy->GetBehaviorTree()->BlackboardAsset, blackboard); 
    
    	RunBehaviorTree(Enemy->GetBehaviorTree()); //트리 실행
    
    }
    
    void ACAIController::OnPerceptionUpdated(const TArray<AActor*>& UpdatedActors)
    {
    	//GetCurrentlyPerceivedActors : 현재 감지되어있는 엑터들 배열 반환 함수
    	//nullptr : 어느걸로 감지되었든 전부 받는다.
    	TArray<AActor*> actors; //감지된 엑터들 저장
    	Perception->GetCurrentlyPerceivedActors(nullptr, actors);
    
    	if (actors.Num() > 0)
    	{
    		//감지된 엑터 배열의 0번을 '타겟'으로 지정한다.
    		Blackboard->SetValueAsObject("Target", actors[0]);
    
    		return;
    	}
    
    	//타겟을 비운다.
    	Blackboard->SetValueAsObject("Target", nullptr);
    }
    
  • BT_Melee
    • 루트 - 디테일 - 블랙보드 에셋 : 생성한 블랙보드 할당
    • 루트 - Selector 검색 후 연결 - Wait 검색 후 연결 - Wait에 우클릭 - 데코레이션 - 블랙보드 클릭 - 디테일 - 블랙보드 - 블랙보드 키 : Target - 키 쿼리 : Is Not Set
  • 결과 : 키 쿼리를 Is Not Set으로 설정했기 때문에, 감지 범위 밖에 있다면 순서대로 실행되고 관잧라 중단 : None이기 때문에 유지되지만, 감지범위로 들어가면 조건이 맞았기에 성공이 반환되고, Selector이기 때문에 Root 노드로 올라가서 실행이 중단된다.

서비스 생성

  • CBTService_Melee
    • 생성 : UBTService 상속
    • BTService 내부에 ‘간격 : Interval’과 ‘랜덤 편차 : RandomDeviation’ 변수가 선언되어있다.
      • TickNode : 랜덤 편차에 의해 생성된 범위에 값이 들어가면 실행되는 노드다.
      • NodeName, Interval, RandomDeviation 등이 선언되어있다.
    • CBTService_Melee의 Owner는 Service를 실행하는 BehaviorTree를 실행하는 컴포넌트가 들어온다.
      • 즉, OwnerComp.GetOwner : BehaviorTree를 실행하는 오너이니 AIController가 들어온다.
    • 헤더 파일 - 생성자 선언 - TickNode 재정의 선언 - ‘ActionRange’ 변수를 선언하고 150으로 초기화한다.
    //header
    private:
    	UPROPERTY(EditAnywhere, Category = "Action")
    		float ActionRange = 150;
    
    public:
    	UCBTService_Melee();
    
    protected:
    	void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
    
    • CPP 파일 - 생성자 정의 - ‘노드 이름’을 ‘Melee’로 설정한다. - ‘간격’을 0.1f로 설정한다. - ‘랜덤 편차’를 0.0f로 설정한다. - TickNode 정의 - 매개 변수로 들어온 서비스의 오너 컴포넌트인 ‘비헤이비어 트리’의 ‘오저 가져오기’함수를 호출하고 해당 트리를 실행하는 엑터가 AIController이기 때문에 해당 클래스로 ‘캐스트’한 결과를 AIController 포인터 변수 ‘컨트롤러’를 선언하고 저장한다. - ‘컨트롤러’의 ‘폰 가져오기’ 함수를 호출하고 해당 폰이 Enemy_AI이기 때문에 해당 클래스로 ‘캐스트’하고 결과를 Enemy_AI 포인터 변수 ‘ai’ 를 선언하고 저장한다.
  • Service 클래스 컴파일 문제
    • LNK2001 : 확인할 수 없는 외부 기호
      • 모듈이 없어서 생기는 문제다.
      • GameplayCameras에서 한번 고쳤던 문제였다.
    • 해결 방법 : 해당 문제가 발생한(__cdecl 다움에 적힌 클래스 명) 클래스 복사 후 구글 검색
      • 언리얼 매뉴얼 사이트 들어가기
      • 해당 클래스 문서로 들어가기
      • References 확인
      • Module 확인 후 복사
      • Build.cs 파일 선택 - AddRange 목록에 붙여넣은 후 컴파일 실행
  • BT_Melee
    • 루트 - Sequence 검색 후 연결 - 우클릭 - 서비스 추가 : 작성한 Service 클래스에서 설정한 NodeName 확인 - Wait 검색 후 연결
  • 결과 : Wait이 실행되는 동안 ‘Melee 서비스’의 TickNode에 정의한 코드대로 계속 실행된다.
    • 이것을 Sequence에 할당하면 성공이 뜨는 모든 순간에 서비스의 TickNode 함수가 호출된다.
    • 이것을 이용해서 값을 설정해서 이용할것이다.

AI 움직임 제어 컴포넌트

  • CAIBehaviorComponent
    • 생성 : 액터 컴포넌트 상속
    • AI의 움직임을 관할할 컴포넌트다.
    • 헤더 파일 - ‘AI 상태 타입’ 열거형 자료형 선언 : ‘대가, 접근, 공격, 순찰, 타격, 회피, 사망’ - 상태가 변하는것을 외부에 알릴 ‘AI 상태 타입 변함’ 델리게이트를 선언하고 ‘이전 타입, 새 타입’을 받을 수 있게 한다. - AI의 상태노드 키 이름을 저장할 ‘AI 상태’ 변수 선언 - 블랙 보드의 키를 맞출 이름 자료형의 ‘타겟 키’ 변수를 선언하고 ‘타겟’으로 초기화한다. - 외부에서 해당 클래스의 상태 타입을 사용하기 위해 ‘타입 가져오기’ 함수 선언 - 상태 확인 함수 : 대기 ~ 사망 확안 함수 선언 - ‘블랙보드 설정’ 함수에 ‘블랙보드 컴포넌트 포인터 변수’를 받을 수 있도록 선언하고 ‘클래스 내부에 선언된 블랙보드에 매개변수로 들어온 블랙보드 저장’으로 정의한다. - 상태 설정 함수 : 대기 ~ 사망 설정 모드 함수 선언 - ‘타입 변경’ 함수를 선언하고 ‘상태 타입 열거형’ 매개 변수를 받을 수 있도록 선언한다. - 델리게이트 변수인 ‘AI 상태 타입 변경됨 활성’ 변수 선언 - 블랙보드 컴포넌트 포인터 변수 ‘블랙보드’ 선언
    //header
    UENUM(BlueprintType)
    enum class EAIStateType : uint8
    {
    	Wait = 0, Approach, Action, Patrol, Hitted, Avoid, Dead, Max,
    };
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FAIStateTypeChanged, EAIStateType, InPrevType, EAIStateType, InNewType);
    
    private:
    	UPROPERTY(EditAnywhere, Category = "Key")
    		FName AIStateTypeKey = "AIState";
    
    	UPROPERTY(EditAnywhere, Category = "Key")
    		FName TargetKey = "Target";
    
    private:
    	EAIStateType GetType(); //현재 상태 타입 가져오기
    
    	//상태 확인 함수
    public:
    	bool IsWaitMode();
    	bool IsApproachMode();
    	bool IsActionMode();
    	bool IsPatrolMode();
    	bool IsHittedMode();
    	bool IsAvoidMode();
    	bool IsDeadMode();
    
    public:	
    	UCAIBehaviorComponent();
    
    protected:
    	virtual void BeginPlay() override;
    
    public:
    	//블렉보드 설정
    	FORCEINLINE void SetBlackboard(class UBlackboardComponent* InBlackboard) { Blackboard = InBlackboard; }
    
    //public:
    	//class ACharacter* GetTarget();
    
    	//상태 설정 함수
    public:
    	void SetWaitMode();
    	void SetApproachMode();
    	void SetActionMode();
    	void SetPatrolMode();
    	void SetHittedMode();
    	void SetAvoidMode();
    	void SetDeadMode();
    
    private:
    	void ChangeType(EAIStateType InType);
    
    public:
    	FAIStateTypeChanged OnAIStateTypeChanged; //AI 상태 변경 델리게이트
    
    private:
    	class UBlackboardComponent* Blackboard; //블렉보드 저장
    
    • CPP 파일 - ‘상태 확인’ 함수 와 ‘상태 설정’ 함수 정의 - 상태 확인 : ‘타입 가져오기’ 함수 호출과 해당 상태가 같은지 확인 결과를 반환한다. - ‘타입 변경’ 함수에 해당 상태를 넣고 호출한다. - ‘타입 변경’ 함수 정의 - ‘타입 가져오기’ 함수 호출 결과를 ‘이전 타입’ 변수를 선언하고 저장한다. - ‘블랙보드’의 ‘열거형 값 설정’ 함수에 ‘AI 상태 타입 키 , 매개변수로 들어온 타입을 uint8로 캐스팅’을 넣고 호출한다. - ‘AI 상태 타입 변함 활성’의 ‘연결 함수 확인’ 함수를 호출한 결과가 true라면 : ‘AI 상태 타입 변함 활성’의 ‘연결 함수 실행’에 ‘이전 타입, 매개 변수 타입’을 넣고 호출한다.
    //CPP
    EAIStateType UCAIBehaviorComponent::GetType()
    {
    	//GetValueAsEnum : 블랙보드에 설정된 열거형 키 타입에 할당된 열거형을 가져온다.
    	return (EAIStateType)Blackboard->GetValueAsEnum(AIStateTypeKey);
    }
    
    //상태 확인 함수
    bool UCAIBehaviorComponent::IsWaitMode()
    {
    	return GetType() == EAIStateType::Wait;
    }
    
    bool UCAIBehaviorComponent::IsApproachMode()
    {
    	return GetType() == EAIStateType::Approach;
    }
    
    bool UCAIBehaviorComponent::IsActionMode()
    {
    	return GetType() == EAIStateType::Action;
    }
    
    bool UCAIBehaviorComponent::IsPatrolMode()
    {
    	return GetType() == EAIStateType::Patrol;
    }
    
    bool UCAIBehaviorComponent::IsHittedMode()
    {
    	return GetType() == EAIStateType::Hitted;
    }
    
    bool UCAIBehaviorComponent::IsAvoidMode()
    {
    	return GetType() == EAIStateType::Avoid;
    }
    
    bool UCAIBehaviorComponent::IsDeadMode()
    {
    	return GetType() == EAIStateType::Dead;
    }
    
    //상태 설정 함수
    void UCAIBehaviorComponent::SetWaitMode()
    {
    	ChangeType(EAIStateType::Wait);
    }
    
    void UCAIBehaviorComponent::SetApproachMode()
    {
    	ChangeType(EAIStateType::Approach);
    }
    
    void UCAIBehaviorComponent::SetActionMode()
    {
    	ChangeType(EAIStateType::Action);
    }
    
    void UCAIBehaviorComponent::SetPatrolMode()
    {
    	ChangeType(EAIStateType::Patrol);
    }
    
    void UCAIBehaviorComponent::SetHittedMode()
    {
    	ChangeType(EAIStateType::Hitted);
    }
    
    void UCAIBehaviorComponent::SetAvoidMode()
    {
    	ChangeType(EAIStateType::Avoid);
    }
    
    void UCAIBehaviorComponent::SetDeadMode()
    {
    	ChangeType(EAIStateType::Dead);
    }
    
    void UCAIBehaviorComponent::ChangeType(EAIStateType InType)
    {
    	EAIStateType prevType = GetType();
    
    	//블렉보드 키를 상태 타입으로 설정
    	Blackboard->SetValueAsEnum(AIStateTypeKey, (uint8)InType);
    
    	if (OnAIStateTypeChanged.IsBound())
    		OnAIStateTypeChanged.Broadcast(prevType, InType);
    }
    
  • CEnemy_AI
    • 헤더 파일 - 생성한 AIBehaviorComponent 포인터 변수 ‘비헤이비어’ 선언
    //header
    UPROPERTY(VisibleAnywhere)
    		class UCAIBehaviorComponent* Behavior;
    
    • CPP 파일 - AIBehaviorComponent 자료형의 ‘액터 컴포넌트 생성’ 함수 선언
    //CPP
    CHelpers::CreateActorComponent<UCAIBehaviorComponent>(this, &Behavior, "Behavior");
    
  • CAIController
    • 원래 Get 함수를 선언해서 Enemy_AI 클래스의 ‘비헤이비어’를 가져와서 저장해야하지만 하지 않은 이유 : 해당 클래스도 ‘컴포넌트’로 생성했기 때문에 CPP 파일에서 GetComponent 함수로 간단하게 가져올 수 있기 때문이다.
      • SetBlackboard를 통해서 값을 세팅하고 그것을 이용하는 것이다.
    • 헤더 파일 - AIBehaviorComponent 포인터 변수 ‘비헤이비어’ 선언
    //header
    class UCAIBehaviorComponent* Behavior;
    
    • CPP 파일 - ‘빙의 활성’ 함수 확인 - ‘컴포넌트 가져오기’ 함수를 AIBehaviorComponent로 지정하고 ‘적’을 넣어서 호출한 결과를 ‘비헤이비어’에 저장한다. - ‘비헤이비어’의 ‘블랙보드 설정’에 ‘블랙보드’를 넣어 호출한다.
    //CPP
    //비헤비어 컴포넌트 가져오기
    Behavior = CHelpers::GetComponent<UCAIBehaviorComponent>(Enemy);
    Behavior->SetBlackboard(Blackboard); //AI 비헤비어 컴포넌트의 'Blackboard'에 컨트롤러의 Blackboard 설정
    
  • BB_Melee
    • 열거형 키 타입 할당 방법 : 열거형 타입으로 바로 들어가면 선언한 역러형 자료형이 나오지 않는다.
      • 열거형 이름 : 코드에서 선언한 ‘열거형 자료형 이름’을 치면 해당 타입으로 자동으로 할당된다.
      • 주의 사항 : 이름이 틀리거나 잘못 선언한다면 나오지 않는다.
        • 나오지 않았다면 뭔가가 잘못된것이니 확인해야한다.
    • 새키 - Enum형 선택 - 이름 ; AIState - 블랙보드 디테일 - 키 타입 - 열거형 이름 - 코드에서 선언한 열거형 자료형 이름 ; EAIStateType
  • 정리 : ChangeType을 하면 ‘블랙보드’의 ‘AIState’ 키에 바꾼 타입을 값으로 준다는 것이다.
    • 이 모든것을 AIController에서 제어한다.

BlackBoard 설명

  • BehaviorTree의 판단에 사용하는 데이터(변수) 집합을 의미한다.
    • NPC의 의사 결정은 블랙보드에 있는 데이터를 기반으로 진행된다.
  • 키 - SelfActor : AI를 실행하고있는 자기 자신
  • 블랙보드 디테일
    • 인스턴스 동기화 됨 : 볼랙보드의 해당 옵션을 체크한 ‘키 값’을 사용하는 모든 객체는 해당 키값을 ‘공유’하게 된다.
      • 나중에 TeamAI 만들때 이것을 체크해서 공유하여 사용하게 된다.

Behavior 설명

  • 배치된 노드 우측 상단 숫자 : 노드 실행 순서
  • Root : 트리의 시작
  • Blanch : 트리의 중간
    • Composite : Task를 어떻게 수행하는지를 결정하는 노드들이다.
      • Selector : 성공하면 부모 노드로 올라가서 성공으로 반환한다.
        • 실패하면 다음 노드로 넘어간다.
        • 즉, 마지막 실행 상태를 부모 노드에게 반환한다.
      • Sequence : 이전 작업이 성공하면 다음 노드로 이동한다.
      • 패러렐 : 메인과 서브가있다.
        • 메인이 끝나면 서브도 끝난다.
        • 메인과 서브의 작업들이 동시에 돌아기면서 동작하지만, 메인이 끝나면 서브들의 작업도 끝난다.
  • Leaf : 트리의 끝
    • Task(작업)로 배치된다.
      • 성공, 실패, 진행중이 있다.
      • Wait : 대기시간이 모드 끝나면 성공을 띄운다.
    • 리프는 Task 하나만 있다.
  • Decorater : 조건(블랙보드 값)을 판단하고 조건을 충족하면 노드를 실행한다.
    • 조건이 맞지 않는다면 해당 노드를 ‘실패’로 띄운다.
      • 조건이 참 : 성공 / 조건이 거짓 : 실패 로 해당 노드를 띄운다.
    • Leaf와 Blanch 어디에나 붙을 수 있다.
    • CoolTime이라는 데코레이션은 쿨타임 시간이 지나면 ‘성공’으로 띄운다.
    • 조건이 맞지 않아 앞으로 실행이 되지 않더라도, 실행 도중 조건이 맞이 않게된다면 이미 실행되는 순서들은 계속 실행된다.
    • 조건이 될 노드는 기획이나 AI 디자이너가 담당하게 된다.
      • 기본적으로는 블랙보드를 사용한다.
    • 키 쿼리
      • Is Set : 키에 값이 설정되었다면 노드를 실행한다.
      • Target is Not Set : 키에 값이 설정되지 않았다면 노드를 실행한다.
    • 관찰자 중단
      • None : 데코의 조건이 맞아 노드가 실행된 후 끝나도 ‘중단 시키지 않고’ 다시 실행 시킨다.
      • Self : 조건을 만족하지 못하면 해당 노드를 중단시키고 ‘실패’로 띄운다.
  • Service : 값을 제공하기 위한 옵션이다.
    • 디테일 - 서비스 - 간격 : 서비스가 실행되는 간격
    • 디테일 - 서비스 - 랜덤 편차 : 간격에 + - 하는 값을 넣고 해당 범위를 간격으로 하는 옵션이다.
    • Run EQS

기본 순서

  • Root - Selector - Sequence - MoveTo : 이동
  • Root - Selector - Sequence - Wait : 대기

'공부 > Unreal' 카테고리의 다른 글

24.08.29  (1) 2024.08.30
24.08.28  (0) 2024.08.30
24.08.26  (1) 2024.08.27
24.08.23  (0) 2024.08.24
24.08.22  (0) 2024.08.24