-
안녕하세요!!!
오늘은 튜토리얼의 클리어가 되는 조건인
소탕할 Boss에 대해서 작업을 하겠습니다!
이렇게 생긴 녀석인데
유니티 에셋 스토어에서 무료로 가져온 에셋입니다.
(상당히 많은 에셋들이 듀토리얼의 Boss로 거쳐갔습니다...)
이 보스의 위치는 이 병사가? 알려주었었죠 ㅎㅎ
바로 스크립트로 넘어가 보겠습니다.
보스를 제어하기 위해 EnemyBoss 스크립트를 만들었고
열거형으로 boss의 상태 값을 선언해 주었습니다.
enum은 상수의 일종으로 const대신 사용하며
const값을 입력하지 않아도 자동으로 0,1,2.... 의 값이 대입됩니다.
(코드가 단순해지며 가독성이 좋고, 상수 이므로 if문 swith문에서 사용이 가능합니다.)
Idle : 대기
Mve : 움직임
Attack : 공격
Return : 복귀
Damaged : 대미지 받음
Die : 죽음
이며 이 열거형을 제어하기 위해 bossState의 변수를 선언해 주었습니다.
나머지 선언 변수들도 한꺼번에 보겠습니다.
MoveDis : 보스가 움직일 수 있는 거리
findDis : 보스가 플레이어를 찾을 거리
atkDis : 보스의 공격 거리
(보스의 움직일수 있는 거리를 초과해 벗어난다면 보스는 복귀를 하게 되며
각 범위 안에 있을 시 해당 상태 값의 동작을 실행합니다.)
currentTime : 현재 시간
attackDelay : 공격 딜레이 시간
(현재 시간을 준 이유는 현재시간을 누적시켜 공격 딜레이 시간 이상이 된다면
공격을 하기 위함입니다.)
player : 플레이어
nav : 보스의 NavMeshAgentf를 담을 변수
ani : 보스의 Animator를 담을 변수
attackPower : 보스의 공격력
maxHp : 보스의 최대 hp
Hp : 보스의 현재 hp
(hp를 나눈 이유는 현재로선 복귀했을 시 최대 hp로 만들어 주기 위함입니다.)
moveSpeed : 보스의 스피드입니다.
hpSlider : 보스의 체력바 Slide입니다.
orizinPos : 보스의 초기 위치 값입니다.
orizinRot : 보스의 초기 회전 값입니다.
(리턴하여 복귀 시 해당 값을 설정해 주기 위함입니다.)
targetTool / targetRect
(보스가 Die 상태 일 시 활성화돼있는 오브젝트를 비활성화해주기 위함입니다.)
attackStep : 공격 스탭입니다.
(보스의 공격 스탭 별로 각 다른 공격을 하게 됩니다)
atk01 / atk02 / atk03
보스의 공격 콜라이더입니다.
(콜라이더를 매 활성화해 놓지 않고 이벤트로 시간에 맞춰 활성/비활성을 하게 구현했습니다.)
text / text_Clear : 보스를 소탕했을 시 띄워줄 텍스트 들입니다.
(TextMeshProUGUI를 사용하기 위해 using TMPro를 선언해 주었습니다.)
Start 함수입니다.
우선 BossState의 초기 상태는 Idle로 지정해 주었으며
각 필요한 값을 변수에 할당해 주었습니다.
EbemyBoss 스크립트의 Update함수입니다.
hp를 동기화해주기 위하여 현재 값 / 최댓값으로
0.0f ~ 1.0f의 값을 갖게 해 주었습니다.
(slide의 value 값은 0.0~1.0의 값을 갖고 있습니다.
ex : 0.5 = 50%입니다.)
BossState의 값이 Idle일 때 실행되는 Idle 함수입니다.
간단히 거리를 측정하기 위해 Distance를 사용하였으며
(Distance와 magnitude , sqrMagnitude의 거리 측정 방법이 있습니다.
여기서 Distance와 magnitude는 과정 및 결과는 같지만
편의를 위해 Distance 함수를 제공하고 있으며
sqrMagnitude는 루트 값을 연산하지 않아 빠르다고 알고 있습니다.)
즉 추적 범위 안에 플레이어가 온다면 BossState의 값을 Move로 바꿔주는 코드입니다.
BossState의 값이 Move일 때 실행되는 Move함수입니다.
이 move 함수에서는 if - else if 문을 통해 3가지 조건을 걸어 주었습니다.
첫째. 보스가 초기위치에서의 거리가 움직일 수 있는 moveDis보다 크다면 복귀를 합니다.
둘째. 보스에서 플레이어의 위치 거리가 공격 범위보다 크다면 플레이어를 향해 이동합니다.
셋째. 보스에서 플레이어의 위치 거리가 공격 범위 안에 포함되어 있다면 공격을 하게 됩니다.
각 복귀 / 공격 은 BossState값을 Return / Attack 값으로 조정을 해 주었고
둘째 else If에서 네비를 멈춰 주고(isStopped = true) 목적지를 초기화 (ResetPath())
를 해주며 경로를 다시 잡아준 이유는,
atkDis 안에 플레이어가 포함되어 있다가, Boss가 공격을 하는 도중 플레이어가 거리를 벗어났을 시
미끄러지듯 움직이는 Boss를 제어하기 위함입니다.
BossState의 값이 Attack일 때 실행되는Attack함수입니다.함수 입니다.
BossState의 상태가 Attack 상태가 되면
LookAt 함수를 통해 Player.position으로 회전을 하게 해 주었습니다.
이후 atkDis의 범위 안에 들어왔다가 Player가 다시 벗어날 수 있기에
Distance 함수로 보스에서 플레이어의 위치를 검사해 atkDis 안에 포함되어 있다면
공격을 실행합니다.
우선 currentTime을 +=연산자로 Time.deltaTime * 1로 +1씩 누적시켜 주었습니다.
(여기서 *1을 해준 이유는, 안 해줘도 여기선 이상 현상이 발생하지 않았지만
player를 작업할 때 +=연산자로 Time.deltaTime의 값을 누적시켜 주면
잘 되다가도 한 번씩 지정 값을 넘어가는 현상이 발생해서입니다.)
(이유를 꼭 알아오겠습니다.)
이렇게 값을 누적시켜 주어 공격 딜레이 이상이 됐다면 Switch(attackStep)으로 각 case에 맞게 실행합니다.
이 attackStep은 Random.range(0,5)로 0부터 4까지의 값을 부여받게 했습니다.
Random.range의 값이 실수면 해당 범위 즉 0f ~ 5f까지 되지만
Random.range의 값이 정수면 해당 범위를 제외한 0 ~ 4까지 됩니다.
case는 attackStep이
0과 1
2와 3
4
로 3가지로 나눴습니다.
이렇게 나눈다면 각 40% / 40% / 20% 확률이 됩니다.
이후 공격을 실행했으면 currentTime = 0으로 바꿔줍니다.
(다시 값을 누적할 때 0부터 하기 위함)
보스의 위치에서 플레이어의 위치가 공격 범위 안에 있지 않다면
실행될 else문입니다.
BossState의 값을 Move로 변경시켜 주어
Move 함수에서 각 거리 값에 맞는 조건문을 실행해 줍니다.
여기서도 마찬가지로 currentTime은 0으로 초기화해주었습니다.
(공격을 실행하지 않았더라도 누적되었던 값을 초기화시켜주어 0부터 새로 누적을 하기 위함입니다.)
Boss의 공격 부분을 영상으로 보시겠습니다.
'유니티 프로젝트 > RPG 듀토리얼' 카테고리의 다른 글
RPG 듀토리얼 01. 에셋 준비물 (in Game 동영상) (0) 2023.08.11 RPG 듀토리얼 17. BOSS!!! 02 / 02 (Return & Die) (0) 2022.05.01 RPG 듀토리얼 16. Store buy and sell (0) 2022.04.26 RPG 듀토리얼 15. Npc Store OpenStore (0) 2022.04.26 RPG 듀토리얼 14. Object Pool & item Gold (0) 2022.04.26