타겟팅 락온

CJB_ny·2021년 12월 21일
0

Mini_MMO_RPG

목록 보기
5/16
post-thumbnail

이제 이어서 우리의 게임 규칙을 적용시켜보도록 하자.

우리는 디아블로 스타일로 만들어 볼 것이다.

그러니까

처음에 클릭을 할 때 땅을 클릭했는지 몬스터를 클릭했는지에 따라서 한번 분기가 될 것이고,

땅을 누른 상태에서 드래그하면 그냥 그대로 움직이는 것이고,

몬스터를 한번 클릭을 하고 다른곳으로 드래그를 한다고 하더라도 몬스터에 "락온"을 한 상태라서 몬스터에게 가는 그런 작업을 해볼 것이다.

그래서 이것을 어떻게 구현을 할지 곰곰히 생각을 해볼 시간이 왔다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
음..일단,
1. LockOnManager를 따로 파야할까?? -> 마우스 커서 부분은 따로 CursorManager를 파지 않았다 -> PlayerController에 때려박아 넣음

2. PlayerController에서 코드를 추가 하는 방식으로 할까? -> 그럼 이 방법으로 한번 해보도록 하자

2-1. 그렇다면 어떻게 구현을 할까? -> 이전시간에 했었던것을 생각해보면 선택지가 2가지 정도 나올거 같다.

  • enum CursorType만들었던거처럼 enum LockOnType을 만들자.
  • OnMouseClicked() 함수에서 코드를 추가해야한다.
  • LockOn() 함수를 만들어서 OnMouseClicked()에 if문을 넣어서 만들어야 한다.

나는 void LockOn()함수를 밖에 만들어서 OnMouseClicked()안에 넣어 줄 거 같다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

다시 수업으로 돌아 오면

중요한것이 마우스를 클릭을 했다가 땟을때 다시 처음으로 클릭을 하는 부분이 중요할 것이다.

우리가 지금까지 작업을 한 것 만으로는 아직 이부분은 구현이 안되어 있다.

다시 코드로 돌아와보면 마우스 관리를 InputManager로 하고있었는데..

InputManager를 유심히 살펴보면은

지금 여기에서
마우스를 눌렀다라는 Press Event랑

손가락으로 누른상태에서 땟을때 Click Event만을 사용을 하고 있었다.

그런데 이것만으로는 사실 우리가 원하는 것을 구현읗 할 수가 없다.

그래서 "마우스를 맨 처음으로 눌렀다!" 라는 event를 추가를 해 줄 차례가 왔다.

그래서 이제 Define으로 넘어와서

여기서 이제 추가할 부분들을 추가를 해주어야 한다.


여기서 PointerDown이라고 해가지고 맨처음으로 땐 상태에서 마우스를 탁 누르는 상태를 PointerDown이라고 하자.
그리고 PointerUp은 마우스를 한번이라도 누른 상태에서 마우스를 때는 것을 PointerUp이라고 할 것이다.

PointerUp이랑 Click이랑 그러면 중첩 되지 않느냐? 하는데
클릭은 순간적으로 진짜 클릭이고 몇초동안 누르고있다가 때지는 않으니까
이것이 차이점이다.
그래서 이렇게 고치는 김에 ClickEvent도 수정을 좀 해보자.

그래서 PointerUp과 Click 이벤트를 구분하기 위해서는

이렇게 InputManager에서 _pressedTime이라는 변수를 하나 두도록하자.

그리고 OnUpdate()함수 안에서 마우스를 눌렀다라고 가정을 하면은

_press는 당연히 뜰 테지만

이 if문 Input.GetMouseButton(0)안에서 PointerDown이 뜰지 말지를 정해줘야 한다.


그래서 한번도 아직 클릭을 한적이 없다면은 이렇게 if문으로 Invoke로 PointerDown으로 알려주도록 하자.

그리고 이것은 사실상 마우스를 땐 상태에서 처음으로 누른 상태가 되는 것이니까, 이떄부터 _pressedTime을 세기 시작할 것이다.


이렇게 _pressedTime을 Time.time으로 만들어 주면 유니티에서 관리하는 그런 시간의 개념이 되는 것이다.
(그런데 이 시간이 현재 시간일 필요는 없고 상대적으로 비교를 할 수 있으면 되는 그런 시간이다)

그리고

else 문에서 지금까지는 그냥 누른 상태에서 손가락 때면 Click이였는데
이제는 수정을 좀 해 주어야 한다.

현재(게임시간)시간 기준으로 Time.time이 현재시간
아까 누른 _pressedTime + 0.2f 보다 작으면 Click으로 인정을 하는 것이다.

그래서 이 상태를 만족을 하지못 하면은 어쨋든 일단 마우스를 눌럿다가 땟으니까
PointerUp이라는 것이다.

그리고 뭐 잊어 먹은 것이 없는지 한번보고


마우스를 땐 상태이니까 _pressedTime을 0이로 다시 초기화를 해주도록 하자.


그래서 이제 이까지 작업이 다 되었으면은 PlayerController로 돌아와보자.


그래서 이제 이 OnMouseClicked이 부분을 수정을 해야되는데

함수이름이 마음에 안든다 -> 왜?
클릭을 해야만 실행되는 함수인거같은 느낌이 든다. 이 함수는 지금 클릭안하고 누르고만 있어도 event가 발생하기 때문에

이렇게 바꿔주도록 하자.

그리고 RaycastHit hit을 밖으로 빼주고

원래 if문에 있던 Physics.Raycast(ray, out hit, 100.0f, _mask);
이녀석도 밖으로 빼주고
bool raycastHit의 변수에 저장을 해주도록하자

레이캐스팅이 된것을 저장 해주기 위해서..

그리고 OnMouseEvent함수에서 switch문으로 evt를 받아서

PointerDown인지 Press상태인지 PointerUp인 상태인지 구별을 해주자.

이렇게

그리고 타겟팅 락온을 할 게임오브젝트도

이렇게 위에다가 미리 뺴놓자

유니티를 실행을 하면 클릭한 부분으로 이동잘되는데 이동하는 중간에 몬스터에 마우스를 갖다대면 바뀌는 현상이 발생한다.(문제)

이동하는 중간에는 마우스커서가 바뀌면 안되니까

UpdataeMousecursor부분에 조건을 넣어주도록하자.

사실은 마우스를 누른 상태라면은 어떠한 방식으로든 아이콘이 바뀌면 안된다.
왜냐하면 이미 마우스를 누른 상태에서 땅을 찍었느냐 아니면 몬스터를 찍었느냐가 결정이 된것이니까


이렇게 만약 GetMouseButton(0)이 true라고 한다면은 바로 return을 때려주도록 하자.

그러면 마우스를 누르고 있는 상태에서는 몬스터에게 마우스커서를 올려놔도 변경되지 않는다 이제.

그러면 이제 락온까지는 잘 되었다.

그러면 이제 몬스터를 클릭을 했을때

몬스터에게 다가가면 이제 때리기 시작해야 할 것이다.

그런데 그전에 우리가 유니티짱을 클릭해서 이동시킬때 이전에 무엇인가에 부딪히면 멈추게 만들어 놨었는데
(누르고 있는 상태에서 어딘가에(못가는곳에)갈려고하면 바로 멈춘다)

보통은 우리가 클릭을 그만할때 멈추는게 좀더 맞지가 않나?(가로막는 것이 있어도 움직일려고하는 시도가 있는 그런것이 더 디아블로 스럽지 않나) 그런 생각이 든다.

그래서 이부분만 살짝 고쳐 볼려고하는데 의외로 간단하다.


UpdateMoving에서 앞에 물체가 있을때 if(Physics.Raycast(transform.position + Vector3.up * 0.5f .....)이런식으로 했었다.

그러면 이제 그냥 내가 마우스를 누르고 있으면 _state를 Idle상태로만 바뀌게 하지 않으면 된다.


내가 마우스를 누르고 있는게 맞다고하면은 _state = PlayerState.Idle로 안변하게 이렇게 코드를 짜주자.

그리고 다른 부분을 잠깐 설명하자면은

우리는 지금 InputManager를 만들어서 자체적으로 Input을 관리하기도 하고있고

유니티 자체의 Input.GetMouseButton이라든가 여러가지 유니티의 Input시리즈들도 잘 사용을 하고 있는 중이다.

유니티의 Input시리즈 이런거

그러면 그냥 유니티에서 제공하는 Input이거만 사용하면되지 왜 InputManager를 따로 파서 사용을 하는지 궁금하기도 하다!

->
사실 대부분의 이유는 이런것이다
InputManager에서 보면은 Click같은 유니티자체에서 뭔가 특별이 정의 해주지 않은 이런것들

이런것들을 우리가 매번 사용할 때마다 구현을 하기에는 너무 어려우니까 Manager에서 클릭이나 드래그같은 것들을 우리가 정의한 방식대로 인식을 하면 굉장히 편할 것이다.

하지만 반대로

이렇게 Press같이 계속 누르고 있는 경우에 Event를 계속 발생시키는 것은 조금 비효율 적인것은 맞다.

그리고 PlayerController에서

OnMouseEvent이 녀석도 마우스를 누르는 동안에는 계속해서 호출이 될텐데

그렇다는 것은 우리가 만든 Event를 받는 버젼으로 만드는 것이 아니라

얘내들(OnMouseEvent에서 받는 녀석들을)을 Update문안에 때려박아 넣은 다음에

switch부분에

case부분을 유니티에서 제공하는 방법으로 만들어 주어도 좋을 것이다.


PointerDown은 유니티의 Input.GetMouseButtonDown(0)에 대응을 한다.

그리고 Press의 경우에는

이런 의미가 되는 것이고

PointerUp == Input.GetMouseButtonUp(0)

이런식으로 유니티의 Input 시리즈를 이용해도 괜찮다.

그래서 Input으로 할지 강의에서 배운대로 할지 다른 방식으로 할지는 그냥 선택의 문제이고

다만 뭐 클릭을 해야한다.

아니면 드래그를 해서 이벤트를 발생 시켜야 한다고 하면은 InputManager처럼 중앙에 있는 Manager를 통해서 발생시키는 것이 조금 더 나을 것이다.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글