ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RPG 듀토리얼 07. Monster(Enemy) Target_Box
    유니티 프로젝트/RPG 듀토리얼

    안녕하세요!!

     

     

    오늘은 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만 있을 때 보다 시각적으로 훨씬 효과적입니다)

     

    targetTool / targetRect


    이 타깃 툴이 사라질 경우를 보겠습니다.

    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으로 맞춰 놨을 시 땅에 가려져 안보이거나 겹쳐 보이는 현상이 생기기 때문입니다.

     

     

    00 : 23초

    다음 글 에서는 Enemy의 이동 구현과 공격 기능을 살펴 보겠습니다.

     

    감사합니다!!

     

    댓글

김효겸 / Tel. 010-7735-0580 / E-mail. dollzzang2@hanmail.net