MMO_RPG_스택#3

CJB_ny·2021년 12월 4일
0

Mini_MMO_RPG

목록 보기
3/16
post-thumbnail

1. 에셋스토어 몬스터 다운 및 폴더정리

일단 몬스터를 몇마리 만들어서 Player를 대충 따라오게 만들고
그다음에 Player랑 몬스터랑 전투하는 그런 부분을 이번 시간에 만들어 볼 것이다.

유니티 짱으로 적군 아군 하면 재미 없으니까 에셋스토어가서 몬스터를 다운 받도록 하자.

강의는 다른애로 했는데 나는 이녀석으로 진행 해볼 것이다.

다운받은후 import해주고
Demo이름을 싹다 Knight로 바꿔준다.

그리고 Resource-> Art산하에 다 넣어줌

그리고 폴더 Knight안에 Models, Animation, Materails로 정리하고 Knight한마리 씬으로 꺼내본다.

그리고 꺼내자마자 우리가 해야 할 일은

이렇게 프리팹에 가가지고 original프리팹을 하나 만들어주자.

그리고 Resource산한에 Animations 폴더 만들고knight애니매이션 옮기고 유니티짱 애니매이션 옮겨준다.

유니티짱에는 공격 모션이 없는데 Knight공격모션을 같이 공용으로 사용할 것이다.

그리고 유니티짱과 마찬가지로

Animation을 컨트롤 할 Animator를 만들어 준다.
예전에 했던 것을 곰곰히 다시 생각해보면

위의 사진에 오른쪽에 있는 Controller를 만들어 줘야한다.

우클릭해서 밑으로 내리면 Animator Controller라는 것이 있었다.

그리고 KnightAnimController라는 이름으로 만들어 준다.

그리고 Knight에다가 드래그 드롭으로

이렇게 사용하도록 넣어 주도록하자.

그리고 아까

KnightAnimController의 화면인데 여기에서 애니매이션을 추가하거나 그런 부분이다.

(오랜만에 해서 기억이 안날 수도 있지만 하다보면 다시 익숙해 지니까 너무 걱정하지 말라)


그리고 일단 이렇게 Animation을 다 넣어 주도록하자.

이까지 해주고 일단 저장을 하도록 하자.

그리고 일단 테스트겸 한번 실행을 해보면

아무 이상없이 잘 돌아 댕긴다.

2. 스탯구현하기

그래서 이제 전투를 구현을 하려면은
몬스터가 나를 때리거나 Player가 몬스터를 때리는 작업을 해야하는데..
하지만 그전에 체력이랑 공격력같은 스탯이 정의가 되어야 전투를 하는 의미가 있다.

그런데 우리가 이런 컨텐츠 관련해서는 아직 뭐 따로 만든 것이 없기때문에 다시 만들어야 한다.

그래서 일단 이렇게 Contents파일을 따로 파준다.


에러가나는데 타고 들어가 보면

이렇게 이름이 곂쳐져서 그런것이였다.
이것은 우리가 데이터 포맷을 정의하기 위해서 사용했던것이다.
그래서 namespace로 감싸주도록하자

namespace는 뭐냐하면은 그냥 별칭이 하나 더 붙는다라고 생각하면 된다.
그래서 이제 Stat에 접근을 할때는 Data.Stat이런식으로 접근을 해야한다는 의미이다.

그래서 우리가 이전에 Json파일 관리할때 실습했던 DataManager에서 코드를 수정해야한다.

Data.으로 접근하게 붙여주도록하자.
그래서 이렇게 Data에 접근을 한다라는 것을 확실하게 알ㄹ주게끔 Data. 으로 접근하게 해주자.
(GameScene에서도 수정을 하자)
그러면 이제 진짜 진짜 에러가 해결되었다.

그래서 일단 Stat으로 와서

기본적으로 몬스터든 Player든 기본적으로 갖추어야 할 것들 부터 생각을 해보자

일단 이정도로 정의를 해주자.
그리고 이렇게만 해놓으면 툴에서 볼 수가 없으니까

이런식으로 붙여줘서 툴에서 보이게 해주자.

그리고 외부에서 사용할 수 있으니까

level property를 만들어주자.
return은 level로 return을 하고 set을 하는 경우에는 _level을 value로 할당받아서 _level을 return하는 형식이다.

그런데 이상한게 왜 [Sereializedfiled]처 만들어 놓고
왜 또 프로퍼티를 만드냐?
=> 그냥 프로퍼티만 만들어 놓으면 툴에서는 뜨지않기때문에(툴에서도 보고싶어서) 만들어 주었다.

이렇게 해주자
(speed는 여러개일 수 있으니까 MoveSpeed로 바꿔주자)

이렇게해서 일단 스탯이 만들어 졌다.
그리고 이제 이부분에서 추가가 되는 부분이 있을 것이다.
다른 뭐 플레이어같은 경우에는 경험치라던 스킬공격력같은 것들 등등..

그래서 PlayerStat으로 하나 더 파주도록 하자.
만들어주고

Stat을 상속받도록 하면 공통적인 부분은 작성을 안해도 된다.

그리고 뭐 경험치랑 골드 정도만 챙겨주도록 하자.

그리고 똑같이 프로퍼티 만들어주자.

그리고 프리팹에 가서

유니티짱에 PlayerStat붙여주고
몬스터는 그냥 일반 Stat을 유니티짱과 똑같이 붙여주도록하자.

이 작업을 나중에 코드에서 GetOrAddComponent로 붙여 주어도 상관은 없다.

그리고 디아블로같은 게임을 보면

이런식으로 마우스를 몬스터에게 갖다대면 마우스커서의 색이 좀 바뀌면서
다가가서 어떠한 모션이나 형태(공격과같은)것을 하게 될텐데
그래서 우리도 그러한 방식으로 몬스터를 누르면 다가가서 퍽퍽퍽치는 것을 구현을 해보도록 하자.

근데 이것을 구현을 하려면은 우리는 지금 땅만 레이케스팅을 하고있는데
몬스터를 대상으로도 레이캐스팅을 해줘야한다.

그래서 우리가 잊어먹고있었는데 이전에 만들어 두었던 Monster라는 Layer가 있는데 이것을 적용시켜주자

이렇게

그래서 이제 레이어 추가했으니 레이캐스팅이되는 Layer가 몬스터인지 아닌지에 따라서 유니티짱이 실행할 코드가 다르게 돌아갈 것이다.
이것을 PlayerController에서 추가를 해주던가 뭐 그렇게 하자.

그래서 PlayerController로 왔는데

딱 들어오자마자 수정해야 할부분이 지금
우리가 아까 Stat으로 _movespeed로 Player나 monster의 speed를 Stat으로 관리하는데 지금 _speed가 있으니까 삭제를 해주자.


여기에 이렇게 _moveSpeed를 몰아 놨으니까

대신 위의 사진처럼 PlayerStat _stat이라는 컴포넌트를 들고 있어야한다.
그래서 무조건 있어야하니까 GetComponent로 gameObject => 나의 주인님을 찾아주세요한다음에 PlayerStat을 들고있는 gameObject를 가져와서 그 PlayerStat이라는 Component를 _stat에 할당을 해준다.

그래서 일단 우리가 _speed를 없애서 아래 에러가나는데 이부분들 수정을 해주도록하자.

그래서 원래는 _speed였는데

_stat.MoveSpeed로 수정을 해주자

그리고 지금은 우리가 모든 값을 0으로 설정을 해주었는데
나중에는 data sheet를 참고를 해가지고 데이터에 있는 값을 초기화를 할텐데..
지금은 그냥

Stat.cs -> Start()안에서 강제로 임시의 값을 넣어주도록하자.

대충 이렇게 임시값을 넣어주도록하자.

그리고 이 Start()함수를 복사해서

_exp, _gold값같이 넣어주자 근데 지금 빨간줄 에러인데
보호수준 때문이다.
Stat에서 protected 붙여줘야한다.(상속받는애들)

이렇게 protected 붙여주고 혹시 모르니까
PlayerStat애들도 protected붙여주도록하자.

이렇게 일단은 싹다 하드코딩으로 만들어 놓자.

그다음에 이제 PlayerrController에서
쫒아간다음에 후드려패는 그런 모션을 구현해야 한다.

그러면이제 죽은거, 움직이는거 Idle, Attack도 추가를 해야하는데
뭐 치유 스킬이나, 공격스킬 이렇게 있을 수 있으니까 Skill이라는 이름으로 만들어 주자.

그다음에 이제 이동 할 때 이제 땅을 선택해서 이동을 하는지 아니면 몬스터를 클릭을 해서 이동을 하는지 구분을 해야한다.
그것은 우리가

여기에서 관리를 하고있었다.
OnMouseClicked()함수로 딱 클릭을 했을 댸 GetMask로 "Wall"이라는 애로 Ray를 판단을 하고 있었다.
우리가 이때까지는 테스트겸 해서 그냥 Wall이라는 이름으로 사용을 했는데 이제는 이름을 변경을 해주자


그래서 Terrain Layer를 Wall로 되있던거 Ground로 바꿔주고
그래서 이제 Ground, Monster둘중에 Ray가 찍히는것을 판별을 해서 해당 Layer에 대한 코드를 실행할 수 있도록 만들어 주면 될것이다.

그리고 코드에서

LayerMask.GetMask("string")이런식으로 계속 "string"넣어줘야하니까 => 하드코딩 Define에서 좀 관리를 해보도록하자.


8, 9, 10은 유니티에서 Add Layer를 보았을때 레이어 순서를 그냥 넣어 준 것이다.

그래서 일단

이렇게 추가가 될텐데 이렇게 GetMask에 string을 이용하는 것은 꺼림찍하다...
매번마다 해야되는데 GetMask(string)이렇게 낭비를 해야 하나 싶기도 하다.
그렇다는 것은 이것을 한번만 계산을 해서 가지고 있으면 되니까 바로 위에다가 추가를 일단 해놓도록하자.

이 계산을 한번만 하는 것을 쉬프트 연산자로 계산을 해주도록하자.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
OnMouseclikcked위에다가 _mask에다가 쉬프트 연산자로 값을 넣어주자.
(지금 쉬프트 연산자의 기본 개념은 아는데 왜 이렇게 하는지 모르겠다.)
아래는 나의 질문글과 답변이다.


1번 질문과 1번의 답변은 이해가 갔다.

근데 어떠한 원리로
Layer.GetMask("string") | Layer.GetMask("string")이 부분을 _mask가 계산을 한번미리해서 대체를 하는 건지 모르겠다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

그리고 일단
Layer.GetMask("string") | Layer.GetMask("string")이 부분을
_mask로 대체를 하자

그리고 레이케스팅이 되었다는 것을 어떻게 알 수 있을까?
레이케스팅이 성공했다는 것은 몬스터 or ground 둘중 하나일것이다.
둘중 하나인것을 그래서 어떻게 판별 할 수 있을까?

=> 어떤애한테 레이저가 먼저 찍혔는지를 알면은 그녀석한테서 Layer를 추출을 해낼 수 있을 것이다.

그래서 레이가 찍힌 녀석이 Monster이냐 아니냐에 따라서 분기를 해주면 될 것이다.

그리고

이렇게 DeBug.Log가 찍히는것만 확인을해주고

유니티에서 지금 Knight는 Collider가 없으니까

이렇게 Capsule Collider를 추가해주고 조금 크기 수정해준다음에 다시 유니티 실행해보면


Ground Clicked 찍히다가 Monster clicked! 가 잘 찍히고 그곳으로 이동을 잘 한다.

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

0개의 댓글