-
이 단원에서는 적의 움직임을
-
제어하는 코드를 작성해 보겠습니다
-
적은 애니메이터로 움직이며
-
앞서 제공한 애니메이션 클립의
-
루트 모션에서 동작을 취합니다
-
애니메이터 매개변수는
애니메이터가 재생하는
-
애니메이션 상태와 그에 따른
-
적의 동작 방식을 제어합니다
-
[Nav Mesh Agent]의 속도를 이용해
-
이 매개변수를 설정할 것이며
-
코드로 값을 조정해 특정 동작을
-
교정해 보겠습니다
-
내브 메쉬를 이용하면 시스템은 에이전트에
-
원하는 속도를 지원합니다
-
이것은 에이전트가 이동하는 실제 속도가
-
아니라, 방향 전환 속도입니다
-
우리의 적과 같은 내브 메쉬 에이전트는
-
여기 붉은 선으로 표시된, 목적지로 향하는
-
중간 경로를 가집니다
-
에이전트는 중간 지점으로 이동하면서
-
중간 지점으로 얼굴을 돌리며,
검은색 화살표로
-
표시된 에이전트의 속도가
녹색 화살표로 표시된
-
원하는 속도로 향하고 있다고
-
우리는 말합니다
-
이 원하는 속도는 적의 애니메이터
-
매개변수인 [Speed] 및 [Angular Speed]로
-
전송할 값의 토대입니다
-
우선 이 매개변수를 제어하는 스크립트를
-
작성해 보겠습니다
-
로봇 가드에 [EnemyAnimation]이라는
-
새 스크립트를 추가합니다
-
[char_robotGuard]를 선택한 후
-
[Add Component] - [New Script]를
-
선택하고 [EnemyAnimation]이라고 합니다
-
편집을 위해 스크립트를
실행하고 준비합니다
-
우선 필요한 클래스 변수를 살펴봅시다
-
필요한 공개 변수는 1개인데
-
부동 변수이며,
이 변수를 [deadZone]이라고
-
하겠습니다
-
입력 용어인 데드존과 유사한 [deadzone]은
-
무시해야 하는 값의 범위입니다
-
적이 길 찾기를 하는 경우
-
적의 전방과 원하는 속도의 차이가
-
매우 적다면, 적이 방향 전환을
-
시도하지 않도록 합니다
-
[deadzone]을 이용해 이를 정의합니다
-
이렇게 하지 않으면
-
예제처럼 적이 오버스티어링하면서
-
똑바로 중간 지점을 향해
-
걸어가지 못합니다
-
6개의 비공개 변수가 필요합니다
-
그 첫 번째는 플레이어의 전환
-
관련 레퍼런스입니다
-
이를 이용해 플레이어가
보일 때 적이 플레이어를
-
향하는 방향을 설정합니다
-
그 다음은 플레이어가 보이느냐 아니냐에
-
따라 애니메이션을 변경할 수 있도록
-
[EnemySight] 스크립트 레퍼런스가
-
필요합니다
-
그리고 적의 이동을 안내할
-
[nav mesh Agent] 컴포넌트
레퍼런스가 필요합니다
-
그 다음에는 애니메이터
컴포넌트 레퍼런스가
-
필요하고, 매개변수 참조 지원을 위해
-
[HashIDs] 스크립트 레퍼런스가
-
필요합니다
-
마지막은 지난 단원에서 작성한
-
헬퍼 클래스의 인스턴스인
-
[AnimatorSetup]입니다
-
그 다음에는 [Awake] 함수를 이용해
-
이 매개변수들을 설정할 것입니다
-
레퍼런스 할당 외에도
-
다양한 액션 수행을 위해 [Awake] 함수가
-
필요할 것입니다
-
우선 적의 회전을 내브 메쉬 에이전트가
-
아니라 애니메이터로 설정하는지
-
확인해야 합니다
-
이렇게 하면 코너를 돌
때 미끄러지는 현상을
-
줄일 수 있습니다
-
또한 앞 단원의 헬퍼 함수
-
인스턴스를 생성하고
-
이와 함께 그 생성자를
-
호출할 것입니다
-
이미 레퍼런스를 확보하고 있는
-
애니메이터 컴포넌트와
[HashIDs] 스크립트를
-
분석할 수 있습니다
-
우리는 여러 애니메이터 레이어의 가중치를
-
설정해야 합니다
-
이 [Weight] 값은 애니메이터에서 레이어의
-
애니메이션 밸런스를 조정합니다
-
[Shooting]과 [Gun] 레이어에
-
1의 가중치를 부여할 것입니다
-
따라서 이 두 레이어는 기본 레이어 등
-
아래에 있는 레이어보다 우선 적용됩니다
-
이는 애니메이션이 순전히 이 레이어들을
-
토대로 함을 뜻합니다
-
하지만 [Shooting]과 [Gun] 레이어에
-
마스크를 사용하고 있으므로
이 레이어들을
-
우선 적용할 수 있는 유일한 신체 부위는
-
각각 상체와 오른손입니다
-
따라서 [Set Layer Weight] 함수와
-
레이어의 정수를 사용합니다
-
가령 기본 레이어를 0으로 참조해야 한다면
-
[Shooting]과 [Gun]을 참조하고 있으므로
-
1을 이용해 [Shooting]을, 2를 이용해
-
[Gun]을 표시할 것이며
-
2개 모두를 [1f]로 설정합니다
-
[Awake] 함수에서 수행해야
하는 마지막 작업은
-
[deadZone] 변수를 '각도'에서 '라디안'으로
-
변환하는 것입니다
-
앞서 작성한 애니메이터
컨트롤러가 라디안으로
-
매개변수를 측정하기 때문이죠
-
다행히 [Mathf] 클래스는 이용할 수 있는
-
상수 [deg2rad]가 있습니다
-
상수는 변수와 비슷하지만
-
일단 설정하면 변경할 수 없습니다
-
'각도'의 숫자를 라디안으로 변환하려면
-
이 상수로 곱하기만 하면 됩니다
-
이 스크립트의 대부분은
내브 메쉬 에이전트를
-
기반으로 애니메이션을 설정합니다
-
이를 위해 [Update]
함수에서 호출할 수 있는
-
함수를 생성할 것입니다
-
이 함수를 [NavAnimSetup]으로
부르기로 합니다
-
이 함수에서 수행할 첫 작업은
-
헬퍼 클래스의 [Setup] 함수에 대해
-
분석할 [Speed] 및 [Angle] 매개변수를 위한
-
부동 변수 2개를 생성하는 것입니다
-
이제 플레이어가 보이는지 결정해야 합니다
-
플레이어가 보이면 적이 멈추도록
-
해야 하므로, [Speed] 매개변수를
-
0으로 설정합니다
-
이제 적이 향해야 하는 방향과 실제로
-
향하고 있는 방향 사이의 각도를
-
파악합니다
-
왼쪽은 -, 오른쪽은 + 입니다
-
이 작업을 수행하려면 또 다른
-
함수를 생성해야 합니다
-
이 함수는 [float]을 반환해야 하며
-
매개변수로 [vector3] 3개가 필요합니다
-
다시 말해 [fromVector]
-
[toVector], 그리고 방향을
-
결정하는 또 다른 벡터가 필요하죠
-
이 함수를 [FindAngle]이라고
-
하겠습니다
-
여기에 분석하려는 [toVector]는
-
내브 메쉬 에이전트의 원하는 속도입니다
-
이것은 종종 0이 됩니다
-
그러면 오류가 발생할 수 있으므로
-
이를 확인할 수 있는
방법을 삽입해야 합니다
-
원하는 속도가 0이라면
-
방향이 0이 되길 원합니다
-
그렇다면 함수에서 간단히 0을
-
반환하면 되고, 그렇지 않다면
-
코드의 나머지 부분으로
-
계속 진행합니다
-
다음 단계는 각도의 절대값을
-
구하는 것입니다
-
[vector3.angle] 함수를 이용해
-
간단하게 구할 수 있습니다
-
그리고 이 각도가 전방의
-
왼쪽 또는 오른쪽이냐를
-
결정합니다 이를 위해
-
두 벡터의 벡터곱을 구해
-
법선 벡터의 합을 확인합니다
-
벡터곱에 왼손 법칙을 적용해
-
[toVector]가 [fromVector]의
오른쪽이라면
-
법선이 윗쪽을 향할 것임을
-
알 수 있습니다
-
이 부분을 복습하려면, 아래 링크의
-
Vector Maths 단원을 참조하십시오
-
이제 이 [Normal]과 우리가 분석한
-
[Up] 벡터의 곱을 구할 수 있습니다
-
[Normal]과 [Up] 벡터가
같은 방향을 가리키면
-
합력은 0보다 클 것이므로
-
우리가 구한 곱의 부호로
-
이미 계산한 각도를
-
곱하면 됩니다
-
그러면 원하는 속도가 [Forward] 벡터의
-
왼쪽 또는 오른쪽인지 파악할 수 있습니다
-
이 각도를 라디안으로 구해야
한다는 점에 유의합니다
-
따라서 앞서 이용한
-
[Deg2Rad] 상수를 곱해야 합니다
-
마지막으로 각도를 반환할 수 있습니다
-
각도를 구하는 함수가 있으므로
-
[NavAnim setup] 함수에서 그것을
-
사용할 수 있습니다
-
[fromVector]는 적의 [forward] 벡터
-
[toVector]는 적에서 플레이어까지의
-
벡터인데, 우리는 적의 [upVector]를
-
[up] 벡터로 이용할 것입니다
-
이제 플레이어가 보이지 않는
-
경우를 해결해야 합니다
-
플레이어가 보이지 않으면
-
속도가 내브 메쉬 에이전트의 원하는
-
속도를 바탕으로 정해지도록 합니다
-
이를 위해 프로젝션을 사용해
-
원하는 속도 벡터를 적의
-
전방 벡터로 투사합니다
-
프로젝션을 통해 벡터 2개를 취할 수 있고
-
다른 벡터의 방향에 있는 첫 번째
-
벡터의 양을 확인할 수 있습니다
-
프로젝션은 첫 번째 벡터의 끝에서
-
두 번째 벡터로 선을 그리면
-
구할 수 있습니다
-
이 선이 두 번째 벡터의 방향과
-
직각을 이루도록
-
그려야 합니다
-
이 선의 교점은 프로젝션 벡터의
-
끝을 정의합니다
-
내브 메쉬 에이전트의 원하는 속도를
-
적의 전방 벡터에 투사하고 있으므로
-
원하는 속도와 같은 방향으로
-
적이 향하지 않는다면 합 벡터는
-
작을 것입니다
-
속도 변수를 프로젝션 벡터의
-
크기로 설정할 것입니다
-
이 프로젝션을 사용하지 않으면
-
적은 빠른 속도로 엉뚱한 방향으로
-
향할 것이므로, 정확한 방향으로 향하려고
-
커다란 아치를 그리면서 뛸 것입니다
-
다음은 각도를 구할 차례입니다
-
여기에서도 [findAngle]
함수를 사용하겠지만
-
이번에는 [toVector]가 내브 메쉬
-
에이전트의 원하는 속도입니다
-
댐핑을 이용해 애니메이터
매개변수를 설정하고
-
있으므로, 방향을 전환할 때
-
정확한 방향을 향하자마자 방향 전환을
-
멈추지는 않을 것이며, 미세하게 계속
-
방향 전환을 시도할 것입니다
-
그런 다음 보정을 위해 되돌아가야 합니다
-
그러면 코너를 돌면서 뱀과 유사한
-
움직임을 보여줍니다
-
이런 움직임을 방지하려면 함수에
-
체크를 삽입합니다
-
이 체크는 각도가 작은지, 즉 [deadZone]
-
변수보다 작은지 확인합니다
-
만약 그렇다면
적이 향하는 방향 설정을 위해
-
애니메이터 컨트롤러를 사용하지 않습니다
-
이를 위해 각도를 0으로 설정하고
-
적의 트랜스폼이 그 위치에서 원하는
-
속도를 바라보도록 설정합니다
-
속도와 각도를 계산했으므로
-
헬퍼 클래스 애니메이터 설정의
-
[Setup] 함수로 분석할 수
-
있습니다
-
그리고 댐핑을 적용하고 애니메이터
-
컨트롤러로 분석하면 됩니다
-
[NavAnimSetup] 함수를 완성했으므로
-
[Update] 함수에서 호출하면 됩니다
-
이미 작성한 함수 위에 이 함수를
-
삽입하는 동안 이 작업은 불필요하다는
-
점에 유의합니다
-
스크립트에 대해 매끄러운
구조를 유지하려고
-
이 작업을 수행합니다
-
우선 클래스 변수가 오고
-
[Awake] 함수를 호출한 다음
-
모든 프레임에서 [Update]
함수를 호출합니다
-
그러면 [NavAnimSetup] 함수와 [FindAngle]
-
함수가 차례로 호출됩니다
-
이 스크립트와 관련해
마지막으로 수행할 작업은
-
적의 루트 모션에
효과를 부여하는 것입니다
-
일반적으로 루트 모션을 적용할 수도 있고
-
애니메이터 컴포넌트에
포함시키지 않을 수도 있습니다
-
하지만 모든 프레임에서 [Update] 후
-
호출되는 [OnAnimatorMove]
함수를 사용한다면
-
수동으로 루트 모션에
효과를 부여할 수 있습니다
-
이 함수에서 제어해야 하는 것은 두 가지
-
즉, 적의 속도와 적의 회전 속도입니다
-
속도를 제어하려면 내브 메쉬 에이전트의
-
속도를 델타 타임으로 나눈 애니메이션의
-
델타 위치로 설정해야 합니다
-
이는 프레임당 위치 변화입니다
-
회전의 경우, 이미 내브 메쉬 에이전트를
-
설정했으므로 이것이
회전을 제어하지는 않습니다
-
따라서 애니메이션의 루트 회전을 직접
-
이용해 회전 효과를 부여할 수 있습니다
-
이로써 스크립트가 완성되었습니다
-
스크립트가 완성되었으므로
-
저장한 후 에디터로 돌아갑니다
-
반드시 [Enemy] 폴더에 스크립트를
-
정리하도록 합니다
-
[Scripts] 폴더를 확장하고
-
에셋의 루트에서
[Enemy] 폴더로 끌어다 놓습니다
-
이제 씬을 저장하고 프로젝트도 저장합니다
-
다음 단원에서는 적이 플레이어를 쏘는
-
스크립트를 작성해 보겠습니다