Destroy#1

CJB_ny·2022년 1월 10일
0

Mini_MMO_RPG

목록 보기
12/16
post-thumbnail

1. 이번 시간에 할것

플레이어랑 몬스터를 어떻게 관리 할것인지에 대한것이다.

우리가 지금까지는

툴을 이용해서 프리팹을 가져와서 씬에다가 배치를 하고있었다.


이런식으로

그런데 이게 뭐 싱글 게임이나 간단한 게임이면 이런식으로 해도 상관은 없지만

MMO_RPG나 큰 게임의 경우 언제 어디서 몬스터가 생성이 될지 모른다.

이런식으로 드래그 드롭으로 만드는 것은 말이 안된다..

그래서 결국에는 몬스터나 플레이어를 중앙에서 관리를 해주는 매니저가 필요하다는 말이 된다.

그래고 이상태에서 플레이어나 몬스터를 찾을려면 딱히 마땅한 방법이 존재 하지 않는다.

이때까지 우리가 한것은 Player에 Tag를 달아서 Player라는 Tag를 가진 녀석을 Scene에서 찾아왔었었다.

하지만 이런 방식들도 조금 문제가 되는 것이 무엇이냐 하면은

나중에 온라인 게임으로 만들게 되었을때 모든 것은 서버랑 통신을 하게되어서 Player를 찾을때 Id 로 찾게 될것이다.

그래서 Player도 그렇고 몬스터도 그렇고 각각의 id를 부여 받아가지고

예를들어 Player는 101번이고 Monster는 202번이라고 하면은 101번이 202번을 공격하게 해줘 라는 식으로 하게될 것이다.

그러면 그 정보를 받은 서버는 그것을 인접한 유져들에게 다 뿌려주게 될 것이고

다른사람이 볼때도 똑같은 화면을 볼 수 있도록 101번과 202번을 찾아가지고 움직여 주고

작동을 시켜야 된다.

하지만 우리가 하는 방식(Tag 로 찾는 방식) 대로 하면은

빠르게 id를 찾는 방법은 없다.

결국에는 새로운 Manager를 추가를 해가지고 중앙에서 관리를 해야된다는 말이다.

그래서 이번시간은 그 작업을 할것인다.

그런데 그전에 굉장히 궁금한 사실이 있는데

우리가 만약에 Manager를 만든다고 치자 그런데 그 안에 무엇을 저장하고 있어야 할지가 큰 문제이다.

예를들어 몬스터와 플레이어를 구분할 수 있는 방법이 뭐가 있을까?? 라고 생각을 해보면

이런
Controller들은 유일하니까
id랑 Controller를 같이 저장하는 방법도 있을 것이고

아니면 id랑 그에 해당하는 GameObject를 들고있게 하여도 괜찮을 거같다.

그런데 만약 id랑 GameObject를 들고왔는데 그 상태에서 GameObject가 날라가면(없어지면) 어떻게 될것인가??

굉장히 궁금한데 -> 어떻게 될것인지가 오늘 수업의 핵심 내용이다.

굉장히 중요한 부분이다.

일단 코드로 와서 MonsterController에서 플레이어의 체력을깍는 부분이 있었는데

이렇게.

우리가

이렇게 Stat을 가져온 상태이니


굳이 여기서 Stat을 GetComponent로 안가져와도된다.

수정하자.

그래서

계속 때리다가 체력이 0이 되면 (죽으면)
DEstroy가 되도록 함 해보자.


이렇게 targetStat.Hp가 0이하가 되면은
Detroy를 하는데 tagerStat을 들고있는 gameObject를 Destroy를 해주도록 하자.

이렇게 하고 어떻게 될지 유니티에서 테스트를 해보도록 하자.

그러면 몬스터가 존나 때리다가 Player오브젝트가 없어지는데

에러가 뜬다.

이렇게 짜잔 하고 크래쉬가 가 난다.

그래서 왜 크래쉬가 났는지 에러를 클릭을 해서 가보면은

CameraController의 34번째 줄이 뜨는데

요기 이렇게

Player는 이제 유효한 애가 아니라 Detroy해서 없앤 상태이다.

그래서 유니티에서 에러를 다시 유심히 읽어 보면은


GameObject가 사라졌는데 니는 계속 접근을 하려고 한다.

그리고 너의 Script는 이것이 null이 아닌지 뭔지 체크를 해야한다.

자 그럼 그렇다는 것은


여기서 _player가 null일 경우 뭔가가 잘못되었다는 것이니까 return;을 일단 떄려주고


여기 breakPoint잡고 -> Unity 연결 -> Unity실행을 하면


여기서 이렇게 바로 걸리는데

그래서 여기 _player를 보면은 null이라는 값이 들어가 있다.

그래서 null체크를 if문으로해서 유효한지 안한지 실험까지는 해보았다.

그런데 처음에 이것을 보았을때는 문화충격이 왔었다고 한다.

어떻게 이것이 가능한지에 대해서

신기하지 않나요??

=> 이게 왜 신기한지 설명을 하자면은

2. C# 레퍼런스 개념

약간 C#기초에 대해서 얘기를 잠깐 하도록 하겠다.

레퍼런스에 대해서 얘기를 해볼 것인데

c#에서 클래스는 무조건 참조 타입이라고 얘기를 했었었다.

참조 타입이라고 하는것은 데이터 본체가 실제 변수에 있는게 아니라

변수에는 그냥 주소값만 들어가있고 그 주소를 따라가면 실제 데이터가 저장이 되어있는 개념이다.


이런식인데 cameraController도 이런식으로 참조를 하는 식이다.

그런데 위에서 break point잡은 부분을 보면 null은 null인데 필기체?null로 되어있다(문자열 null)

그래서 그냥 유니티 자체에서는 메모리에 들고있는데

참조값이 다 해제되지 않았으니까

들고는 있을텐데

null체크를 할때 "null"을 null로 인지를 하게끔

"강제"로 만들어 준 것이다.

근데 이것을 기본 행동을 하지 않고 뭔가를 할 수 있게 만들어 주는것은 (가능하게 해주었다는것은) "오퍼레이터 오버로딩"을 했다는 얘기인데

그래서 GameObject타고 타고 들어가보면 Object에서 유니티자체로 가라를 해주는 부분이 있다.

그래서 어쨋든

이부분에서 == 으로 유효한지 안한지 확인을 할 수 있다.

그래서 또 중요한 것이

어떤 이유에서든 GameObject가 날라갔다라고 가정을 하면은

그 날라간 오브젝트가 들고있던 컴포넌트들도 더이상 사용을 하면 안된다라는 말이 된다.

예를들어 우리가 가끔 Manager코드에서 가끔 GameObject를 들고있는게 아니라

그냥 그 녀석이 가지고있는 컴포넌트를 들고 있는 경우가 상당히 있었다.

예를들어 UI_Manager로 가보면은


이런식으로 GameObject가 아니라 GameObject가 들고있는

컴포넌트인 <UI_Popup>를 들고 있었다.

그런데 이렇게 관리를 할때는 항상 조심해야하는게

얘가 들고있는 컴포넌트의 주인이 삭제가 되면은

접근을 하자마자 바로 "크래쉬"가 난다.

그러니까 사실은 우리가 굉장히 위험한 짓을 하고있었던 것이다.

그래서 결론은 이렇게 오브젝트를 관리를 하고 컴포넌트를 관리를 하는 것은 좋지만

이런 "생명 주기"를 항상 신경을 써주어야 한다.

일단 Manager에서


이런식으로 다른곳에서도 쓰이는 프레임워크 같은 느낌의 Manager는 Core에 넣고

이 게임에서만 쓰이는 애들은 Contents에 밀어 버리자.

그리고 GameManager를 하나 만들어주는데

굉장히 특이하게도 아이콘이

이렇게 다른것을 볼 수 있는데

이거 그냥 버그라고 한다.


그래서 Ex만들고 위에 삭제를 하자.

이녀석같은 경우에는

정말 특수한 녀석이다.

이제는 뭐 더이상 엔진(Core에 있는 녀석들)과 관련이 있는 것이 아니라

우리 contents에서 몬스터와 플레이어를 관리를 하기위한

그런 매니저로 일단 만든 것이다.

만약 여기서도 기능이 너무 많이 진다면

WorldObjectManager이런식으로 나누어서 해도 될거같은데
일단은 많이 질거같지 않으니까 여기서 다 관리를 해주도록 하자.

이렇게

Manager의 새식구를 추가를 해주고 #region으로 구역을 나누어 주자.

그래서 다음시간에 GameManagerEx는 무엇을 들고 있어야 하는지 생각을 함 해보도록 하자.

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

0개의 댓글