AI컨트롤러 & BST

CJB_ny·2023년 1월 2일
0

득언리얼

목록 보기
7/12
post-thumbnail

https://velog.io/@ounols/%EA%B2%8C%EC%9E%84-%EC%88%98%ED%95%99-1.-3%EC%B0%A8%EC%9B%90-%EA%B3%B5%EA%B0%84-%EB%A7%9B%EB%B3%B4%EA%B8%B0

언리얼 아키텍쳐

위의 링크를 보면은

이런식으로 Pawn에는 PC랑 AIController 가 빙의될 수 있다.

AIController를 통해서 Pawn을 플레이어처럼 움직일 수 있게 할 것이다.

모르는? 궁금한 부분들

  • StaticClass()

    CDO && StaticClass

  • PlacedInWorldOrSpawned

    앞으로 레벨에 배치하거나 새롭게 생성되는 ABCharacter마다 ABAIController액터가 생성되고 플레이어가 조종하는 캐릭터를 제외하고 모두 ABAIController의 지배를 받는다.

NavMesh깔기

NavMesh깔아서 랜덤 좌표로 막 이동시키는 부분구현연습 해봄.

AIController이정도로 만들어두고 테스트하면은

굿굿


BehaviorTree

  • BlackBoard

    인공지능의 판단에 사용하는 데이터 집합을 의미한다. (데이터 집합이다)
    NPC의 의사 결정은 블랙보드에 있는 데이터를 기반으로 진행된다.

  • BehaviorTree

    NPC가 해야할 행동을 분석하고 우선순위가 높은 행동부터 NPC가 실행할 수 있도록 트리 구조로 설계하는 기법.

    블랙보드 데이터에 기반해 설계한 비헤이비어 트리의 정보를 저장한 애셋이다. 언리얼 에디터에서는 비헤이비어 트리를 시각화해 저장할 수 있도록 편집 기능을 제공함.

Task는 독립적으로 실행될 수 없고 반드시 Composite노드를 거쳐 실행되어야한다.

"컴포짓 노드"에는 대표적으로

  • Selector
  • Sequence

가 있는데, 연결된 Task들이 False결과가 나올 때까지 왼쪽에서 오른쪽으로 Task를 계속 실행하는 시퀀스 컴포짓을 선택해보도록 하겠다.

BST의 task실행

BST가 task를 실행할 때는 태스크 클래스의 ExecuteTask라는 멤버함수를 실행한다.

ExecuteTask함수는 다음의 넷중 하나의 값을 반환해야한다.

  • Aborted : 테스크 실행중에 중단 되었다. 결과적으로 실패했다.
  • Failed : 테스크를 수행했지만 실패했다.
  • Succeeded : 테스크를 성공적으로 수행했다.
  • InProgress : 테스크를 계속 수행하고있다. 테스크의 실행 결과는 향후 알려줄 예정이다.

ExecuteTask함수의 실행결과에 따라 컴포짓 내에있는 다음 태스크를 계속 수행할지 중단할지가 결정된다.

현재 사용중인 시퀀스 컴포짓은 자신에 속한 태스크를 실패할 때까지 계속 실행하는 성질을 가진다.


NavigationSystemV1 ❗

이거 버전 바뀌고나서 이득우에서는 NavigationSystem으로 되어있는거에서

NavigationSystemV1으로 바꿔주어야한다.


NPC 추격 구현 👍👍👍

"컴포짓 노드"에는 대표적으로

  • Selector
  • Sequence

Selector를 통해 behaviorTree로직을 분기를 하고 추격 기능을 넣기 위해 "서비스 노드"를 통해서 구현을 하도록 하자.

"서비스노드"는 언리얼에서 제공하는 노드임. 독립적으로 동작하지 않고 컴포짓 노드에 부착되는 노드이다.
또한 "서비스 노드"는 task들이 실행되는 동안 반복적인 작업을 실행하는데 적합하다.

즉, 플레이어를 감지를 하는 서비스노드를 만들고 이를 Selector컴포짓에 추가하면 BehaviorTree는 플레이어를 감지하는 루틴을 계속 반복한다.

BehaviorTree의 ServiceNode는 자신이 속한 컴포짓 노드가 활성화 될 경우 주기적으로 TickNode함수를 호출한다.

호출하는 주기는 서비스노드의 내부에 설정된 Interval속성값으로 저장할 수 있다.

추격할 경우

추격할 경우 계속 에러가 발생했었음.

Target은 찾은뒤에 범위에서 벗어나도 Node의 Target값이 nullptr로 변경이 안되서 계속 쫒아옴.

그래서 이부분을 아래와 같이 수정을 함.

이후에는 범위에서 벗어나면

BehaviorTree의 오른쪽으로 바로 가고 범위안에 있다면 바로 왼쪽 노드를 실행하러옴.

Target은 Blackboard의 값인데 이 Blackboard의 값의 여부에 따라 특정 컴포짓 여부를 결정하는 데코레이터 노드를 사용하는 것을 추천한다.

키값의 변경이 감지되면 현재 컴포짓 노드의 실행을 곧바로 취소하도록 노티파이 옵저버값을 On Value Change로 바꿔 주어야한다.

오른쪽 상단에 On Value Change로 해주어야 BlackboardKey값이 변경여부에 따라 노드의 실행을 바로 취소하고 실행하러갈 노드로 간다.

NPC의 공격 ❗

한 또 한시간 ~ 한시간 반정도 해맨 부분이 있는데

TargetOn일 경우의 컴포짓을 Sequence가 아니라 Selector로 변경했어야 했다.

공격할지 말지를 분기를 해야하기 때문인데 TargetOn컴포짓을 계속 Sequenece로 놔두어서 루트에서 동작을 안했었다.

최종적으로 위와 같은 모양이 되어야함.

BT는 Task를 실행할 때 Task클래스의 ExecuteTask라는 멤버 함수를 실행한다.
ExecuteTask힘수는 다음의 넷 중하나의 값을 반환해야한다.

  • Aborted : 테스크 실행중에 중단 되었다. 결과적으로 실패했다.
  • Failed : 테스크를 수행했지만 실패했다.
  • Succeeded : 테스크를 성공적으로 수행했다.
  • InProgress : 테스크를 계속 수행하고있다. 테스크의 실행 결과는 향후 알려줄 예정이다.

공격하는 Task는 공격 애니매이션이 끝날 때까지 대기해야하는 지연 상태 Task이므로

InProgress를 반환하고 공격이 끝나면 Task가 끝났다고 알려주어야한다.

Attack이라는 Task를 실행하면 위와같은 코드가 실행된다.

ABCharacter의 Attack함수를 실행하고 람다로 묶어줌.

ABCharaceter의 Attack이 끝나면 BroadCast하도록 함. 이부분을 람다로 묶은 거임.

이후에 TickTask에서 람다에서 받은 IsAttacking이 false가 된다면 FinishLatentTask함수를 실행할 수 있도록 해준다.

Turn ❗❗❗

이번에 또 회전과 관련된 부분 나온다.

공격은 잘되는데 회전후 공격이 안되서 해당 Task를 구현을 함.

지금 뭐 ABCharacter의 TargetKey얻어와서 Target가져옴.

이로부터 LookVector를 구하는데 Target->GetActorLocation() - ABCharacter->getACtorLocation()으로 방향? 벡터 얻음. 그리고 Z축을 0으로 맞춤.

그리고나서 TargetRot을 만드는데 MakeFromX로 X축으로부터의 회전행렬을 만들겠다라는것임.

이전에 정리 해놓은거도 있음 MakeFromX 보도록 하자.

RInterpTo를 사용해서 "회전 보간"을 한다.

얻은점 👍👍👍

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글