K-digital traning/Final Project

Gazzlers 개발일지 - Enemy 공격

내꺼블로그 2023. 12. 27. 15:51

기존에 R&D했던 Enemy 공격 부분을 구현하는 작업을 진행해보았다.

(팀장님의 GameScene을 받아 제작해보았슴댯,,,,ㅎ)

 

 

(1) Enemy

추가된 필드는 다음과 같다.

muzzleTrans : 총알이 발사될 지점

muzzleGo : player를 향해 겨눌 총구의 object

playerTrans : 적이 공격할 player의 transform

attackCount : 공격 횟수(한 번 공격을 시작할 때 몇 번 쏠 것인지)

dealLossTime : attackCount만큼 공격할 때 간격(주기)

onAttackPlayer : enemy가 player 공격에 성공했을 때 main에게 알리는 대리자

onCompleteAttack : enemy가 attackCount만큼 공격을 다 하고 난 뒤 main에게 알리는 대리자

isAttack : 현재 enemy가 공격하는 중인지 아닌지를 알리는 상태

 

 

 

다음과 같이 각각의 enemy prefab들에게 muzzleTrans, muzzleGo, AttackCount, DealLossTime 할당

 

 

 

player를 향해 총을 조준하는 함수

enemy의 muzzleGo는 player 방향으로 rotation한다.

 

 

 

player를 공격하는 함수

dealLossTime 간격으로 총알을 발사해야 하므로 Coroutine을 사용

AttackPlayer 함수는 GameMain에서 호출된다.

 

 

player 공격하는 Coroutine 함수

attackCount만큼 총구에서 총알(bullet)이 발사된다.

(bulletGenerator를 통해 총알이 생성되면 총알에 붙은 Bullet 스크립트가 총알의 움직임을 구현해준다.)

bullet.Init을 실행할 때 매개변수로 Action을 받는다. 이 Action은 총알이 player를 명중했을 때 호출될 함수이며 이 함수는 GameMain에서 구현되어 있다.

공격이 다 끝난 경우 GameMain에게 공격 완료를 알리기 위해 onCompleteAttack를 호출한다.

 

 

enemy가 죽을 때 추가된 부분.

enemy가 공격중인 상태에서 죽을 시에도 onCompleteAttack를 호출하도록 설정하였다.

 

 

(2) Bullet

 

target : bullet이 날아갈 대상의 transform

moveSpeed : bullet의 속도(참고로 8로 지정했다.(5 아님))

onAttackPlayer : player를 명중했을 때 호출될 대리자. Init으로 대리자를 할당받음.

 

 

 

 

GameObject.Find를 통해 공격 target을 받는다.

(this.targetPos 부분은 지금 쓸모 없는 것이니 보지 않아도 됨.)

GetComponent<RigidBody>()를 통해 bullet에 붙어있는 RigidBody를 this.rBody에 할당한다.

 

 

원작 게임에서처럼 총알이 player로 유도되도록 LookAt을 사용한다.

MovePosition을 사용하여 총알이 현재 위치에서 자신의 앞방향으로 moveSpeed 속도로 이동하도록 구현한다.

만약 bullet의 위치가 player의 위치보다 뒤에 있을 경우 이미 지나친 것으로 간주하여 gameobject를 제거한다.

 

 

 

총알에서 충돌이 발생했을 시에도 gameobject가 제거되도록 한다.

이때 총알에 부딪힌 gameObject가 player인 경우 player를 공격한 것으로 간주하여 onAttackPlayer를 호출한다.

 

 

 

 

(3)GameMain

GameMain 스크립트에 새로 추가한 필드는 다음과 같다.

enemyAttackCoolTime : enemy가 공격을 시작하기 위해 돌아야 되는 시간

enemyAttackelapsedTime : enemy가 공격하기까지 흐르는 시간

isEnemyAttack : enemy가 공격 중인지 아닌지를 나타내는 상태

enemyAttackIdx : listEnemies에서 공격을 시킬 enemy의 index

 

 

 

화면에 enemy가 나타나 있는 상태 + enemy가 공격중이 아닐 경우 enemyAttackelapsedTime이 흐르도록 설정.

만약 enemyAttackelapsedTime이 enemyAttackCoolTime보다 클 경우 쿨타임이 다 돈 것으로 간주하여 listEnemies에 있는 enemy들 중 하나를 골라 AttackPlayer를 호출하도록 한다.

그 뒤 enemy가 공격중이므로 isEnemyAttack는 true로 변경한다.

enemyAttackIdx++%this.listEnemies.Count는 enemy들이 번갈아가며 공격하도록 구현된것으로 enemyAttackIdx는 후위증가하도록 하여 AttackPlayer호출 이후에 값이 증가되도록 하였고, listEnemies의 Count를 벗어나지 않게 하기 위해 mod 연산을 넣었다.

if문 안의 조건문에 해당되지 않을 경우 enemyAttackelapsedTime=0, isEnemyAttack=false.

 

 

enemy 생성되는 부분에서 추가구현한 부분.

enemy가 공격에 성공했을 시 enemy의 Damage를 DataManager로부터 받아옴.

enemy가 공격을 완료했을 시 공격상태가 아니므로 isEnemyAttack는 false, enemyAttackelapsedTime = 0f가 되도록 설정.

 

 

 

결과