ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RPG 액션 연습 04. Bomb_Idle
    연습 프로젝트/RPG 연습

    안녕하세요.

    오늘은 Bomb Enemy를 만들어볼 예정입니다.

    다양한 몬스터를 만들어보려고 이것저것 구상 중인데,

     

    우선 서있는 Bomb Enemy와 움직이는 Bomb Enemy로 총 2 종류를 만들 예정입니다.

     

    이런 두 종류인데..

    제가 손 글씨에 영.... (악필은 천재가 많다고 합니다) (라는 변명이 많다고 합니다)

    정리해서 보자면

    1. 가만히 있는 Bomb Enemy / 움직이는 Bomb Enemy | 로 총 2종류입니다.

    - 가만히 있는 Bomb Enemy는 일정 반경 안에 Player가 접근 시 죽으면서 폭발을 일으키는 Enemy입니다.

    - 움직이는 BombEnemy는 항상 Player를 향해 움직이며 접근한 시간이 일정 시간 이상이면 폭발을 일으킵니다.

     

    우선 이렇게 2명의 Enemy를 제작해 보겠습니다.


    우선 Bomb Enemy를 제작하기에 앞서 

    유니티 에셋에서 무료 다운로드를 통해 받아오겠습니다.

     

    우선 가만히 서있는 Bomb Enemy부터 제작할 예정입니다.

    게임 뷰 창에서 바라볼 때의 모습입니다.

    이 아이를 Bomb_Idle로 명칭을 정해주고 

    계획한 동작 구현에 맞게 진행해 보겠습니다!

     (처음에 100% 원하는 에셋은 아니었는데 계속 보다 보니 귀여운 감이 없지 않아 있는 것 같기도 한 것 같고...)

     

    선언 변수들과 Start 함수입니다.

    traceRadius : 플레이어를 찾을 반경입니다.

     

    curTime : 플레이어가 반경 안에 들어와 일정 시간 후 폭발을 

    일으키는데 Time을 재 줄 시간입니다.

     

    boomIn = 플레이어가 범위 안에 들어와 있을 경우를 체크해줄 불 변수입니다.

     

    message : TextMeshProUGUI Text입니다.

    택스트 메쉬 프로를 사용하기 위해 네임스페이스 using TMPro 부분을 선언했습니다.

     

    anim : Bomb_Idle의 애니메이터 컴포넌트입니다.

     

    boom_Effect : Bomb_Idle 이 폭발 시 생겨날 이펙트입니다.

     

    tr : Bomb_Idle의 Transform입니다.

    (매번 불러서 사용하는 것보다, 변수로 받아서 사용하는 것이 미세하지만 조금 더 빠르다고 하여서

    transform을 불러오는 대신 tr의 변수에 담아서 사용하였습니다)

     

    audio : Bomb_Idle의 오디오 소스 컴포넌트입니다.

    밑에 저 녹색 줄이 신경 쓰여서 뭐지? 하고선 밑줄을 마우스로 갖다 대보니

    상속된 'Component.audio' 멤버를 숨깁니다. 숨기려면 new 키워드를 사용하라는 말 밖에는 없었습니다.

    막상 이렇게 new키워드를 붙이면 실로 녹색 밑줄이 사라졌는데

    결과는 알지만 과정을 모르는 상태의 찝찝함을 갖고 싶지 않아 검색을 통하여 찾아보기로 했습니다.

     

    잠깐의 생각으로는 새로운 오디오 소스를 추가하려면 new 키워드를 사용해야 하나?

    라는 생각을 잠깐 하기도 했었지만

    찾아본 결과 audio라는 키워드가 내부적으로 어딘가에서 이미 쓰이고 있는 예약어라고 합니다.

    조금만 더 나아가 보자면, 상속 상태중 하위 클래스에서 상위 클래스에 있는 함수명을

    똑같이 쓰게 되면 뜨는 밑줄이라고 합니다.

    변수 이름을 변경하거나 new키워드를 붙이면 해결이 되는 거였습니다.

     

    검색을 통해 찾아본 것이지만 분명 몰랐던 분들도 계실 것?이라고 생각하기에

    먼저 알게 된 지식 선배로써 알려드리겠습니다 후후


    우선 new 키워드를 사용하여 녹색 밑줄을 해결하였습니다.

     

    Start함수 에선

    GetComponent로 각 tr / anim / audio 변수에게

    Transform / Animator / AudioSource를 추가시켜주었으며

    시간을 재어줄 curTime = 0으로 초기화해주었습니다.

    여기서도 OnDrawGizos 함수를 활용해 씬 뷰 상에서

    범위를 시각화로 확인할 수 있게 사용했습니다.

     

     

    우선 Bomb_Idle의 OnTriggerEnter 함수부터 보겠습니다.

    Enter / Stay / Exit는 이제 말 안 해도 다들 아실 테지만.. 한번 더

    Enter : 물체가 접근했을 시

    Stay : 물체가 머무를 시

    Exit : 물체가 떨어질 시

     

    그중 Enter : 물체가 접근했을 시 / other의 태그를 검사에 태그가 "Player"라면

    Animator의 SetTrigger를 이용해 "IdleToRot"을 트리거 체크를 해주어 Animator의 트랜지션 방향으로 전환되게 합니다.

    Bomb_Idle Animator

    이후 Player가 접근 중임을 체크하는 불 변수 boomIn = true로 바꿔주었으며

    TextMeshProUGUI로 받아온 message의 gameObject는 SetActive(true)로 활성화시켜줍니다

    audio.PlayOneShot 함수를 통해 사운드를 진행시켜줍니다. 

    Play 함수로도 소리 재생은 되지만 소리가 중첩된다 기억하자.!

    이제 이 OnTriggerEnter 함수에서 반응이 체크가 되어 boomIn이 true가 되면 실행되어 줄 조건문들입니다.

    Update 함수에서 실행하였습니다.

     

    curTime += Time.deltaTime을 통하여 1초씩 더해 줍니다.

     

    if(curTime >= 3.0f)

    의 조건문인 curTime이 3초 이상이 된다면

    ExpEffect() 함수를 실행시켜 줍니다.

     

    // 잠시 ExpEffect() 함수 부분부터 보겠습니다 //

    Collider []를 담아줄 coll의 변수를 선언하고 Physics.OverlapSphere 함수를 이용해 

    Collider 들을 받아 옵니다.

     

    Physics.OverlapSphere의 인자는 (원점, 반지름, 검출 대상 레이어)입니다.

    여기 레이어에선 비트 연산 표기법을 사용하여 다양한 논리 연산이 가능하기 때문에

    1 << 6 | 1 << 7 : OR연산, 6번 또는 7번 레이어 가 되기에

    한 레이어만 검색하는 것이 아닌 다양한 연출도 가능할뿐더러

    ~(1<<6)과 같은 NOT연산으로. 6번 레이어를 제외한 나머지 모든 레이어도 가능하다.

     

    6번 레이어는 Player를 뜻하고 Player의 콜라이더를 검출해 내서

    coll이 null이 아니라면? 플레이어가 받는 대미지 함수인 DamageAction 함수에 (5 만큼의 파워)

    를 주는 함수 구현입니다.

     

    이를 이용하면 폭파를 시키거나 근 대미지를 입히는 상황의 연출이 가능할 것 같습니다.

    //

     

    다시 Update로 돌아와

    message.color = Color.red

    message.fontSize = 150f
     message.text = "BOOM!!!"

    로 컬러는 red / 폰트 사이즈는 150f / 그리고 보일 텍스트는 "BOOM!!!"을 외치게 됩니다.

     

    BOOM을 외치며 폭발과 함께 Bomb_Idle은 죽어야 하기에

    anim.Play("die") : Play 함수를 통한 "die" animation 실행


    audio.PlayOneShot(Manager.instance.manager_SE.boom_Idle_Die)

    PlayOneShot으로 사운드 재생


    boom_Effect.SetActive(true)

    폭발 이펙트는 true로 만들어 주며

    Disable 스크립트를 재활용하여 비활성화되게 해 줍니다.

     

    StartCoroutine(Die())
    boomIn = false

    플레이어가 범위 안에 있는지 체크할 boomIn은 펄스로 바꿔주고

     

    StartCorutine으로 Die 코 루틴 함수를 실행시켜 줍니다.

     

    코루틴 Die 함수

     

    Die 함수는 간단합니다.

    Bomb_Idle 이 죽으면서 죽는 애니메이션을 할 시간을 기다리기 위해 

    yield return new WaitForSecondsRealtime으로 (2.0f) 2.0f초를 기다렸습니다.

    여기서 WaitForSecondsRealtime 말고 WaitForSeconds 도 있는데

    둘 다 똑같은 매개변수로 입력한 숫자에 해당하는 초만 큼 기다렸다가 실행되는 코드라고 하는데

     

    성능의 차이를 찾아보려고 했지만, 아직 찾지 못하였습니다.

    참고로 WaitForSecondsRealtime 은 TimeScale의 영향을 받지 않는다고 합니다.

     

    이제 완성!! 

     

    이 된 것 같지만

     

    치명적인 오류가 존재합니다.

     

    우선 플레이어가 접근해서 지정 시간이 지나면 폭파하며 모션을 취하는 건 정상 동작을 합니다.

     

    그러나, 플레이어가 접근했다가 다시 범위를 벗어날 시 boomIn이 체크가 되어 있기에 그대로 Update 문에서 정상 동작을 합니다.

     

    이러한 구현을 원하는 분들도 계시겠지만, 전 플레이어가 범위 안에 있을 시에만 동작 구현을 시키고 싶기에

     

    OnTriggerExit 함수를 사용하기로 했습니다.

    Exit : 충돌 물체가 떨어질 시입니다.

    떨어진 물체가 (other)의 태그가 "Player"일 시

    "Rot" 애니메이션에서 Idle로 가는 트랜지션 방향에 "RotToIdle이라는 트리거를 의 조건을 걸어 주었고

    curTime = 0으로 초기화하여 다시 접근 시 0초부터 시작하게 만들었습니다.

    문제 부분이었던 boomIn 부분을 false로 바꿔주었으며

    message도 SetActive를 통하여 false

    마지막으로 audio도 Stop 함수로 즉시 멈춰 주었습니다.

     

    아 참 한 가지 빠트린 점이 있는데

    Player를 바라보게 하는 LookAt 기능이 또 쓰일 것 같아서 스크립트로 만들어 주었습니다.

    Bomb_Idle 에게 입혀진 LookAt 스크립트

     

    00 : 21초

     

    댓글

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