-
안녕하세요!!
오늘은 Monster를 만들어볼 예정입니다.
구현할 Monster를 Enemy로 칭하겠습니다.
(Enemy가 손에 익었습니다..)유니티 에셋 스토어에서 무료로 다운로드하였습니다.
우선 Enemy에 관련해서 구현할 목록부터 정리하겠습니다.
//
1. Enemy를 클릭 시 타기팅 박스를 만드는 과정을 볼 것입니다.
2. Enemy의 상태 값에 따른 동작 구현을 볼 것입니다.
3. Player의 Skill 동작 구현을 볼 것입니다.
(Player의 Skill에 따른 Enemy 동작 구현)
//
흠.. 일단 머릿속에서 그려지는 게 아직은 이 정도입니다.
하나하나 설명을 이어 나가면서
추가될 부분은 추가하며 글을 작성하겠습니다.
이 타기팅 박스에 대해 간략히 설명하자면,
Enemy를 터치 / 클릭 시 타겟팅 박스가 활성화되며
Player의 스킬이 그 타기팅 박스가 활성화 된 곳으로 나가게 됩니다.
타기팅 박스가 활성화가 안되어 있다면, Player의 스킬은 일직선 으로 나가게 되며
날아가는 도중 Enemy가 맞는다면 그 Enemy 에게는 타겟팅 박스가 활성화가 됩니다.
자. 그럼 이제 타겟팅 박스부터 만들어 보겠습니다!!!!
고고씽~
동작 구현을 코드를 설명드리기 위해 Test용 Enemy를 가져왔습니다.
현재 만들 타게팅 박스는
이런 식으로 만들어 봤습니다.
조준점이 잡힌 뒤 NameText로 Enemy의 이름을 알려주며
체력바 가 적용된 모습입니다.
이 체력바는 Slide 가 아닌
간단한 이미지 두장을 겹쳐 놓은 상태로 뒷 B / 앞 F
를 지정해 F 이미지의 Fill Amount를 조절하여 만들어 봤습니다.
UI 항목은 간단히 보고 바로 코드로 들어가겠습니다.
이 타기팅 박스가 실행될 스크립트는 PlayerController입니다.
변수 선언 부분부터 간략하게 보겠습니다.
target : 타깃 된 오브젝트입니다.
target_Tool : 타깃 조준점(박스)입니다.
target_Name : 타깃의 이름입니다.
target_Hpbar : 타깃의 체력바입니다.
이후
OnPointerDown이벤트에서
ray를 발사하여 hit에 저장 한 뒤
if(hit.transform.tag == "Player") 조건문으로
Player를 클릭하면 info & bag 창이 활성화 되게 만들었었죠?
(ray에 충돌 감지를 하기 위해선 collider가 꼭 필요합니다)
//
이 부분에서 hit.transform.tag 가 "Enemy" 라면 타기팅 박스가 활성화 되게 구현할 것입니다.
이 Targeting 함수는 hit.transform의 태그를 검사해서 타게팅을 실행시키는 함수입니다.
//
이렇게 나눈 이유는 Collider를 갖고 있는 모든 물체에게 타기팅이 발생한다면 예기치 못한 상황이 발생할 수 있습니다.
한 가지 예를 보자면. Npc는 체력바가 필요 없는 오브젝트인데, 동작 구현을 나누지 않는다면
NPC에게 체력바를 띄워줄 것을 요구하는 예기치 못한 상황이 발생할 수 있습니다. (기타 등등)
Enemy에 실행되는 동작 구현과 또 다른 상호 작용을 하는 오브젝트들을 실행되는 구현을 각각 나눌 필요가 있었습니다.
//
우선 Targeting 함수에서 태그가 Enemy라면의 조건을 보겠습니다.
hit(충 감지된 녀석)의 transform을 target에 대입해 줍니다.
이후 if(target의 태그가 == "Enemy" 라면?)의 조건을 걸어 검색하게 해 줍니다.
위의 if조건문이 성립하여 들어왔다면.
오브젝트는 Enemy인 것으로 판단하고
target의 이름 / 타깃의 hpBar을 Obj_Info에서 가져옵니다.
//
(이 Obj_Info는
단순히 Enemy에게 입혀질 것으로 이름과 타입이 나타내어져 있습니다.
obj_Name은 Enemy의 이름을 나타내기 위해서.
obj_Type 은 Enemy의 타입을 조건 검사하기 위해서입니다.
(같은 Enemy라도 다른 종류의 타입이 존재할 수 있습니다))
//
또한 targetTool과 targetRect를 SetActive = true로 활성화를 시켜주는 모습입니다.
targetTool : 타깃 박스(조준점)
targetRect : 아래 확인용 원형 발판입니다.
(타 모바일 게임을 보고 따라 해 봤습니다 ㅎㅎ targetTool만 있을 때 보다 시각적으로 훨씬 효과적입니다)
이 타깃 툴이 사라질 경우를 보겠습니다.
1. Enemy가 죽는다.
2. 다른 타깃을 지정한다.
3. 일정 거리 이상이면 사라진다.
1. 번은 Enemy의 상태 값은 동작 구현에서 Enemy가 죽을 시 볼 것이고
2. 번은 현재 OnPointerDown이벤트에서 터치 한 곳이 Enemy 일 시
Targeting 함수가 실행되고 있습니다.
이제 알아볼 3. 번 일정 거리 이상이면 사라진다
의 코드 내용을 보겠습니다.
이 OnTarget() 함수는 Update문에서 실행됩니다.
매 실행되면 안 되기에 if(target!= null)의 조건을 걸어
target이 비어있는 상태를 나타내며
현재 터치를 한 오브젝트가 비어있지 않을 시 실행되도록 조건을 걸어준 모습입니다.
targetDis = (target.position - player.transform.position). magnitude
타깃과 플레이어의 거리를 계산하여 magnitude로 변환해 주었습니다.
항상 Distance만 사용을 했었는데, 이 길이를 반환해주는 magnitude를 사용해
float 값인 targetDis에 넣어 주어 조건을 계산하는 데 사용해 보았습니다.
Distance와 magnitude는 같은 역할을 합니다.
편의를 위해 Distance를 제공하며
정확한 거리 계산이 가능하며
또 한 가지 거리를 체크할 때 사용하는 sqrMagnitude가 있습니다.
sqrMagnitudes는 제곱 값을 반환해 주기에 루트 연산을 하지 않아 속도가 빠르다고 합니다.
아직 한 번도 사용해보진 않았습니다.
현재 만들 Enemy들은 Idle 상태 일 시 맵을 자유롭게 돌아다닙니다.
선제공격을 하는 타입이 아니며, 공격 & 스킬을 받았을 시 에만
플레이어를 따라오며 공격하게 구현이 되어있습니다.
플레이어와 target (현재 Enemy)의 거리를 targetDis에 검색해 주고
if(targetDis > range) 만일 타깃이 움직일 수 있는 거리보다 크면
타깃은 null로 비어있음을 나타내 주고
타깃툴과 타겟 원형 발판은 SetActive를 활용해 false로 비활성화 해 줍니다.
즉 타겟 툴을 킨 상태에서 플레이어가 Enemy로부터 일정 거리 이상 멀어지거나
Enemy가 플레이어로부터 일정 거리 이상 멀어지면 타깃 툴은 비활성화됩니다.
위의
if(targetDis > range) 조건이 실행이 안된다면
현재 움직일 수 있는 거리 안에서 활동 중이라는 얘기니
target_Tool.position = cam.WorldToScreenPoint(target.position + new Vector3(0, 0.5f, 0))
타깃 툴의 포지션은 캠이 보는 월드 좌표에서 화면 좌표로 바꿔주는 WorldToScreenPoint를 이용해
타깃의 위치에서 알맞게 new vector3로 y축을 0.5f 만큼 올려주는 코드입니다.
또한 target_Rect는 단순 오브젝트로 만들었으니 target(현재 Enemy)의 위치에서 new vector3로 y축을 0.1f만큼 올려주는 코드입니다.
y축을 0.1만큼 올려주는 이유는 0으로 맞춰 놨을 시 땅에 가려져 안보이거나 겹쳐 보이는 현상이 생기기 때문입니다.
다음 글 에서는 Enemy의 이동 구현과 공격 기능을 살펴 보겠습니다.
감사합니다!!
'유니티 프로젝트 > RPG 듀토리얼' 카테고리의 다른 글
RPG 듀토리얼 09. Player Skill (CoolTime ) (0) 2022.04.22 RPG 듀토리얼 08. Monster(Enemy) AI & Attack (0) 2022.04.21 RPG 듀토리얼 06. Item equip (0) 2022.04.20 RPG 듀토리얼 05. ITEM_in the Bag (0) 2022.04.19 RPG 듀토리얼 04. RenderTexture & stat (0) 2022.04.17