이번 영상에서는 유니티 엔진에서 에셋과 스크립트 파일을 공유하기 위해서 사용되는 유니티 패키지 파일의 연결 프로그램이 끊어져서 실행 중인 유니티 에디터에 제대로 임포트 되지 않는 문제를 해결하는 방법을 알아보도록 하겠습니다.
문제
유니티 엔진 버전 관리를 위해서 설치된 여러 버전의 유니티 엔진 중 하나를 지우는 경우, 유니티 패키지인 .unitypackage 확장자의 연결 프로그램이 끊어지는 문제가 가끔 발생합니다.
텍스트 파일 같은 간단한 파일이라면 윈도우 연결 프로그램에서 연결해주면 문제가 해결되지만, 유니티 패키지 파일은 현재 실행되고 있는 유니티 에디터를 찾아서 에셋을 임포트시켜야 하기 때문에 연결 프로그램을 설정하는 것만으로는 문제가 해결되지 않습니다.
유니티 패키지 다시 연결하기
그럼 유니티 패키지 파일을 다시 유니티 에디터에 정상적으로 연결하는 방법을 알아보겠습니다.
먼저 유니티가 설치된 경로를 찾아야 합니다.
유니티를 설치할 때 경로를 수정하지 않았다면 대부분은 C드라이브의 Program Files 폴더에서 Unity 폴더를 찾을 수 있습니다.
Unity 폴더에서 Hub / Editor 폴더로 내려가 보면 설치되어 있는 여러 버전의 유니티 엔진을 볼 수 있습니다.
이 중에서 가장 자주 사용하는 유니티 버전을 선택합니다.
그 다음에는 윈도우 키를 누르고 "cmd"를 입력하면 명령 프롬프트를 찾을 수 있습니다.
여기서 바로 명령 프롬프트를 실행하지 말고 우클릭 하여 우클릭 메뉴를 띄운 뒤 관리자 권한으로 실행해줍니다.
그리고 명령 프롬프트에서 ftype 명령어를 입력해줍니다.
명령어를 직접 입력하기가 번거롭다면 영상 하단에서 복사해서 사용하면 됩니다.
경로는 앞에서 확인한 유니티 에디터의 실행 파일 경로를 입력해줍니다.
그리고 윈도우에서 파일 이름 확장명 연결을 수정하는데 사용되는 assoc 명령어를 입력해줍니다.
명령어를 모두 입력한 다음에는 명령 프롬프트 창을 닫아줍니다.
그 다음에는 프로젝트에 임포트할 유니티 패키지 파일이 있는 경로로 돌아가서 유니티 패키지 파일을 더블클릭하면 파일을 열 때 사용할 앱을 선택하는 창이 뜨는데 여기서 Unity Editor를 선택하면 실행되어 있는 유니티 에디터를 통해서 프로젝트에 정상적으로 임포트되는 모습을 볼 수 있습니다.
아웃트로
이번 영상에서는 .unitypackage 파일의 확장자 연결이 끊어졌을 때의 해결 방법을 알아보았습니다.
이상 베르의 게임 개발 유튜브였습니다. 감사합니다.
[참고자료]
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
이번 영상에서는 유니티에서 에셋을 전달하기 위해서 사용되는 유니티 패키지에 대해서 알아보도록 하겠습니다.
압축파일 전달
유니티에 익숙하지 못한 입문자일 때는 프로젝트나 프로젝트 안에 있는 텍스처, 머티리얼, 프리팹, 스크립트 같은 에셋을 공유하거나 전달하려고 프로젝트 전체를 압축해서 보내거나 전달할 에셋을 선택하여 압축해서 보내는 방법을 주로 사용했었습니다.
저도 유니티를 처음 배웠을 때는 그렇게 많이 했었죠.
하지만 이 방법을 사용하면 굉장히 많은 문제가 발생합니다.
전체 프로젝트를 압축해서 옮기면 프로젝트의 크기에 따라서 압축 파일의 용량이 너무 커져서 옮기기가 어려워 집니다.
물론 프로젝트에 필요한 폴더만 묶어서 압축하면 훨씬 압축파일의 용량이 줄어들지만, 이렇게 옮기면 프로젝트를 받은 사람이 처음 열 때 시간이 많이 걸린다는 단점도 있습니다.
그리고 압축 파일 이름에 버전을 적어둬도 어떤 게 어떤 버전인지 헷갈리는 문제도 발생합니다.
거기에 가장 치명적인 단점으로는 수동으로 파일을 선택할 때는 프리팹이나 씬에 포함된 오브젝트의 참조 관계, 즉 어떤 프로퍼티에 어떤 프리팹이나 텍스처 등의 에셋들이 꽂혀있는지 전부 알 수 없기 때문에 빠지는 파일이 생길 수 있습니다.
그렇게 되면 전달된 에셋들이 제대로 동작하지 않는 문제가 발생하게 됩니다.
유니티 패키지
앞에서 말한 압축 파일로 에셋을 전달하는 방법에서 발생하는 문제를 해결할 수 있는게 바로 유니티 패키지입니다.
먼저 유니티 패키지를 만드는 방법부터 보여드리겠습니다.
유니티 에디터의 프로젝트 뷰에서 유니티 패키지로 익스포트할 에셋을 선택합니다.
그 에셋에 우클릭하고 [Export Package]를 선택합니다.
그러면 Exporting Package 창이 뜨면서 선택한 에셋과 연관된 에셋, 즉 종속성을 가진 에셋들이 함께 자동으로 선택됩니다.
물론 프로젝트 크기가 커지면 이 종속성이 상당히 복잡해서 정말 필요한 에셋 뿐만 아니라 곁다리 수준으로만 엮인 에셋들도 선택되서 쓸데없는 에셋들이 함께 익스포트되는 경우도 있기 때문에 잘 확인하고 꼭 익스포트할 에셋들만 선택해야 합니다.
그리고 창에서 Include dependency 체크를 해제하면 정말 선택한 에셋만 잡히는데 지금 선택한 프리팹의 경우에는 필요한 3D 모델, 애니메이터 컨트롤러 등이 모두 빠지기 때문에 빈 오브젝트만 익스포트됩니다.
그래서 이 Include dependency 옵션은 보통은 정말 필요한 리소스 에셋이나 스크립트 에셋만 빼내야 할 때 체크를 해제해주면 됩니다.
이렇게 익스포트할 에셋을 모두 선택한 다음에는 Export 버튼을 누르고 저장하고자 하는 위치에 이 패키지가 무엇을 담고 있는지 확실하게 알 수 있는 이름으로 저장해주면 됩니다.
그리고나서 이 유니티 패키지를 임포트할 프로젝트를 실행하고 패키지 파일을 더블클릭해주면 패키지 안에 담긴 에셋들을 그 프로젝트에 넣을 수 있게 됩니다.
버전 관리 도구로써는? 글쎄...
이렇게 유니티 패키지를 사용하면 자신이 개발한 내용이나 기능, 에셋 등을 다른 사람에게 공유할 수 있게 됩니다.
하지만 유니티 패키지를 프로젝트의 버전 관리 도구처럼 사용하려고 해서는 안됩니다.
프로젝트의 버전 관리는 개발 내용의 최신화가 아주 중요한데, 패키지를 전달 받은 다른 개발자가 자신의 프로젝트에 적용하는 작업을 까먹고 안할 수도 있고, 전달 과정에서 몇몇 사람들을 빼먹고 전달하는 경우도 있을 수 있어서 프로젝트의 최신화를 공통적으로 유지하기 어렵습니다.
그리고 이 패키지를 임포트하는 작업은 같은 에셋이 존재하는 경우에 수정 사항을 완전히 덮어씌워버리기 때문에 작업 내용이 겹치거나 잘못된 작업이 임포트되었을 때, 되돌릴 방법이 없다는 것도 문제입니다.
그렇기 때문에 유니티 패키지는 프로젝트의 버전 관리를 위한 방법으로는 적절하지 못하며, 프로젝트 버전 관리는 SVN이나 깃을 사용하는 것이 좋습니다.
깃허브를 이용해서 유니티 프로젝트를 관리하는 방법을 소개하는 영상은 영상 링크를 통해서 확인하실 수 있습니다.
유니티 패키지 사용법
그러면 유니티 패키지는 어디에 사용하면 좋은지 궁금하신 분들이 계실 겁니다.
물론 저는 거기에 답변을 드려야겠죠.
유니티 패키지는 필요한 에셋들을 선택해서 각 에셋 사이의 참조나 종속성 연결을 끊기지 않게 가져올 수 있다는 점에 초점을 맞춰야 합니다.
그래서 필요한 에셋들을 다른 프로젝트에서 가져올 수 있는 것입니다.
예를 들어 예전에 만들었던 게임이 있다고 해봅시다.
그리고 그 다음 게임을 만들려고 하는데 예전에 만들었던 게임과 유사한 형태의 인벤토리 시스템을 넣으려고 한다고 가정해봅시다.
이러면 새 프로젝트에서 완전히 새롭게 인벤토리 시스템을 짜는 것보다 이전 프로젝트에 들어있는 인벤토리 에셋들을 유니티 패키지로 익스포트해서 가져오는 편이 훨씬 나을 겁니다.
또 다른 예시로는 새 프로젝트를 만들어두고 여기에는 인벤토리 시스템만을 구현하는 방식으로 아예 특수한 기능만 구현하는 유니티 프로젝트를 만드는 것입니다.
그리고 이 프로젝트에는 이 시스템을 어떻게 사용해야 하는지 알려주는 샘플 씬과 각종 에셋, 그리고 설명서까지 넣어둡니다.
그 다음에 이 인벤토리 시스템이 필요한 프로젝트가 생기면 이 인벤토리만 구현된 프로젝트에서 관련 에셋들을 유니티 패키지로 익스포트해서 인벤토리 시스템이 필요한 프로젝트에 임포트 시키는 거죠.
사실 대부분의 유니티 에셋 스토어에 올라온 에셋들이 이렇게 필요한 기능만 구현된 프로젝트에서 패키지만 익스포트하는 방식과 유사하게 동작합니다.
아웃트로
이번 영상에서는 유니티에서 에셋을 묶어서 전달하는 기능인 유니티 패키지에 대해서 알아보았습니다.
이상 베르의 게임 개발 유튜브였습니다. 감사합니다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
이번에는 신고 이후에 플레이어들끼리 투표하고 가장 많은 표를 받은 플레이어를 추방하는 기능을 만드는 과정을 진행해보겠습니다.
회의 UI 배치
작업에 들어가기에 앞서 영상 하단의 링크에서 리소스 패키지를 다운로드 받아서 프로젝트에 임포트해줍니다.
리소스 임포트가 완료된 다음에는 회의 UI를 배치해보겠습니다.
먼저 Canvas 오브젝트 아래에 Image 게임오브젝트를 생성하고 화면 전체를 덮도록 세팅한 다음 색을 투명하게 만들어줍니다.
그 아래에는 임포트한 리소스들을 이용해서 실제 게임 화면과 유사하게 배치해줍니다.
그리고 플레이어 패널을 만들어야 합니다.
패널을 만들고 플레이어 이미지를 올린 다음 닉네임을 표시할 텍스트를 추가해줍니다.
그리고 빈 게임오브젝트를 추가하고 Horizontal Layout Group 컴포넌트와 Content Size Fitter 컴포넌트를 붙여줍니다.
그리고 Horizontal Layout Group의 Child Alignment는 Middle Left로 변경하고 Content Size Fitter의 프로퍼티는 Min Size로 변경해줍니다.
그리고 이 레이아웃 그룹 오브젝트의 Pivot X 값을 0으로 맞춰줍니다.
그러면 이 레이아웃 그룹 오브젝트 밑에 다른 플레이어가 투표했음을 표시하는 이미지를 추가하면 제대로 정렬되어서 추가되는 모습을 볼 수 있습니다.
그 다음에는 빈 게임오브젝트도 추가해서 그 아래에 투표 버튼과 취소 버튼도 올려줍니다.
그리고 투표했을 때 표시되는 UI와 죽은 플레이어에게 표시되는 부가 UI까지 올려줍니다.
플레이어 패널을 완성한 다음에는 빈 게임오브젝트를 만들고 Grid Layout Group 컴포넌트를 붙여줍니다.
그리고 Sell Size를 348x63으로 변경하고 플레이어 패널을 복제해서 2열 5행으로 배치되게 크기를 맞추고 간격을 조절해줍니다.
그리고 그 아래쪽에 Skip vote 버튼과 투표를 스킵한 플레이어를 보여주는 UI를 만들어줍니다.
투표를 스킵한 플레이어를 보여주는 UI를 만들 때는 플레이어 패널에서 다른 플레이어가 투표했음을 보여주는 UI와 똑같이 만들어주면 됩니다.
기본적인 배치를 마친 다음에는 만든 플레이어 패널과 투표 표시용 캐릭터 이미지를 프리팹으로 만들어주고 배치되어 있는 오브젝트는 삭제해줍니다.
그리고 Skipped Voting UI도 숨겨줍니다.
플레이어 패널 띄우기
이제 이 Meeting UI의 기능을 차례대로 만들어보겠습니다.
먼저 플레이어 패널에 붙일 MeetingPlayerPanel 스크립트를 생성하고 스크립트 에디터를 엽니다.
스크립트 에디터가 열리고 나면 스크립트의 상단에 UnityEngine.UI 네임스페이스를 using 선언해줍니다.
그리고 멤버 변수로 캐릭터 이미지 색을 바꾸는데 쓰일 Image 타입의 characterImg 변수와 닉네임을 표시하는데 쓰일 Text 타입의 nicknameText 변수, 죽은 플레이어를 표시할 때 사용될 GameObject 타입의 deadPlayerBlock과 신고자를 표시하기 위한 reporterSign 변수를 추가해줍니다.
그리고 어떤 플레이어의 패널인지 구분하기 위한 용도로 IngameCharacterMover 타입의 targetPlayer 변수도 만들어줍니다.
그 다음에는 SetPlayer 함수를 만들어서 characterImg의 머티리얼을 인스턴싱하고 매개변수로 받아온 캐릭터를 저장한 뒤에 캐릭터 이미지의 색을 바꾸고 닉네임을 세팅해줍니다.
그리고 임포스터인 플레이어가 다른 임포스터 플레이어의 패널을 볼 때는 이름이 빨간색으로 표시되도록 만들어줍니다.
그리고 패널의 대상이 되는 플레이어가 죽은 상태라면 플레이어 패널을 가리는 회색 패널이 켜지도록 만들어줍니다.
마지막으로는 해당 플레이어가 신고자라면 확성기 모양의 이미지가 활성화되도록 해야하는데 관련 변수가 없는 상태이니 IngameCharacterMover 클래스로 이동해서 bool 타입으로 isReporter 변수를 추가하고 SyncVar 어트리뷰트를 붙여줍니다.
그리고 아래 쪽에 있는 CmdReport 함수에서 isReporter 변수를 true로 변경하게 만들어줍니다.
다시 MeetingPlayerPanel 스크립트로 돌아와서 targetPlayer가 isReporter라면 reporterSign을 활성화시키도록 코드를 작성합니다.
코드를 모두 작성한 다음에는 저장하고 에디터로 돌아가서 Meeting Player Panel 오브젝트에 작성한 컴포넌트를 붙여줍니다.
그리고 각 프로퍼티를 할당해줍니다.
잠시 앞에서 빼먹은 확성기 모양의 신고자 표시 이미지를 추가하고 비활성화한 뒤 프로퍼티에 할당해줍니다.
그 다음에는 MeetingUI라는 이름으로 C# 스크립트를 생성하고 스크립트 에디터를 엽니다.
스크립트 에디터가 열리고 나면 스크립트의 상단에 UnityEngine.UI 네임스페이스를 using 선언해줍니다.
그리고 멤버 변수로는 플레이어 패널 프리팹을 담고 있을 GameObject 타입의 playerPanelPrefab 변수와 생성된 플레이어 패널들의 부모 오브젝트가 될 Transform 타입의 playerPanelsParent 변수, 그리고 생성된 플레이어 패널들을 저장하고 있을 List<MeetingPlayerPanel> 타입의 meetingPlayerPanels 변수를 선언해줍니다.
변수 선언을 끝낸 다음에는 Open 함수를 만들고 내 캐릭터의 패널을 먼저 만들어서 배치해주고 그 후에 FindObjectsOfType 함수로 다른 플레이어들을 찾아서 각 플레이어의 패널을 만들어 줍니다.
그 다음에는 IngameUIManager 스크립트로 이동해서 MeetingUI를 캐싱해서 접근하기 쉽게 만들어줍니다.
그리고 GameSystem 스크립트로 이동해서 StartMeeting_Coroutine 함수를 만들고 3초 후에 Report UI를 닫고 Meeting UI를 열도록 코드를 작성합니다.
그리고 이 StartMeeting_Coroutine 함수를 RpcSendReportSign 함수에서 호출하도록 만들어 줍니다.
코드를 모두 작성한 다음에는 저장하고 에디터로 돌아갑니다.
에디터로 돌아온 다음에는 Meeting UI 오브젝트에 작성한 컴포넌트를 붙이고 프로퍼티를 할당해줍니다.
그리고 Canvas 오브젝트에 붙어있는 IngameUIManager 컴포넌트에 MeetingUI를 캐싱해줍니다.
작업을 끝낸 다음에는 게임을 빌드합니다.
빌드가 완료되면 게임을 실행하고 테스트합니다.
시체를 발견하고 리포트 버튼을 누르면 리포트 UI가 뜬 뒤에 Meeting UI가 뜨고 죽은 플레이어는 어두운 색으로 표시되고 신고한 플레이어에게는 확성기 마크가 뜬 모습을 확인할 수 있습니다.
패널 선택 기능 만들기
이제 플레이어 패널을 선택하는 기능을 만들 차례입니다.
플레이어 패널을 선택했을 때 투표를 위한 버튼을 뜨게 해야합니다.
MeetingPlayerPanel 스크립트를 엽니다.
그리고 GameObject 타입으로 투표 버튼 그룹을 컨트롤할 voteButtons 변수를 선언하고 패널을 클릭했을 때 동작할 OnClickPlayerPanel 함수를 만들어줍니다.
이 함수에서는 먼저 voteButtons를 활성화시키도록 코드를 작성해줍니다.
코드를 작성한 다음에는 저장하고 에디터로 돌아갑니다.
그리고 프리팹에서 Vote Buttons 프로퍼티에 Player Panel 프리팹 아래에 있는 Vote Buttons 게임오브젝트를 할당해줍니다.
그 다음에는 Player Panel 오브젝트에 Button 컴포넌트를 붙인 다음 Transition을 None으로 변경하고 On Click 이벤트에 Meeting Player Panel의 OnClickPlayerPanel 함수를 등록해줍니다.
작업을 마치면 게임을 빌드해서 테스트 합니다.
회의 창이 뜬 이후에 플레이어 패널을 클릭해보면 투표를 위한 체크 버튼과 X 버튼이 뜨는 모습을 볼 수 있습니다.
그런데 지금은 다른 플레이어 패널을 선택했을 때 앞에서 선택한 플레이어 패널의 버튼이 사라지지도 않고 죽은 플레이어도 선택해서 투표를 할 수 있습니다.
그리고 죽은 플레이어도 다른 플레이어에게 투표할 수 있죠.
스크립트로 돌아가서 이 부분들을 수정해보겠습니다.
먼저 죽은 플레이어의 패널이 클릭되지 않도록 하는 부분은 SetPlayer 함수에서 처리하면 됩니다.
deadPlayerBlock을 활성화하기 위해서 판정한 값을 isDead 변수에 따로 저장해서 사용하도록 코드를 수정합니다.
그리고 isDead 값을 GetComponet 함수로 가져온 버튼의 interactable에 넣어줍니다.
그 다음은 한 패널을 선택했을 때 다른 패널의 선택을 해제하는 것입니다.
이것을 위해서는 다른 패널에 접근이 가능해야하는데 생성된 패널들은 MeetingUI에서 가지고 있으니 그쪽을 통해서 접근하는 것이 좋습니다.
먼저 MeetingPlayerPanel 클래스에 Unselect 함수를 만들어서 voteButtons를 비활성화 시키도록 만들어줍니다.
그 다음에는 MeetingUI 클래스로 이동해서 SelectPlayerPanel 함수를 만들고 선택한 패널을 제외한 다른 패널을 비활성화시키도록 코드를 작성합니다.
그리고 다시 MeetingPlayerPanel 클래스의 OnClickPlayerPanel 함수로 이동해서 MeetingUI의 SelectPlayerPanel 함수를 호출하도록 만들어줍니다.
마지막으로 죽은 플레이어가 투표를 하지 못하게 막기 위해서는 OnClickPlayerPanel 함수에서 플레이어가 죽은 상태라면 투표 기능이 동작하지 못하게 만들어줍니다.
코드를 모두 작성한 다음에는 저장하고 에디터로 돌아갑니다.
그리고 프리팹의 Vote Buttons 아래에 있는 Cancel Button을 선택하고 On Click 이벤트에 Unselect 함수를 등록해줍니다.
작업을 모두 마치면 게임을 빌드합니다.
그리고 게임을 실행해서 테스트해보면 한 패널을 선택하고 다른 패널을 선택하면 이전에 선택한 다른 패널의 선택이 취소되고 죽은 플레이어의 패널은 선택되지 않는 것을 볼 수 있습니다.
그리고 X 버튼을 누르면 패널 선택이 취소되는 모습도 볼 수 있습니다.
마지막으로 죽은 플레이어는 다른 플레이어를 선택할 수 없는 모습도 볼 수 있습니다.
아웃트로
이번 영상에서는 회의에서 임포스터로 의심되는 플레이어에게 투표해서 추방하는 기능을 만들기 위해 회의 UI를 만들고 플레이어 패널을 선택하는 기능을 만들어 보았습니다.
이상 베르의 게임 개발 유튜브였습니다. 감사합니다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
지난 강좌까지 크루원을 죽이는 기능을 만들었으니 이번 영상에서는 크루원의 시체를 발견하면 신고하는 기능을 만들어봅시다.
시체 감지해서 리포트 버튼 활성화 시키기
제일 먼저 해야할 작업은 플레이어가 시체를 감지했을 때 리포트 버튼을 활성화시키는 것입니다.
그러기 위해서는 시체 오브젝트에 감지할 수 있는 콜라이더를 추가해줘야 합니다.
프로젝트 뷰에서 Deadbody 프리팹을 찾아서 선택합니다.
그리고 캐릭터를 감지할 CircleCollider2D 컴포넌트를 부착해준 뒤 is Trigger 프로퍼티를 체크해줍니다.
그리고 캐릭터가 감지하게 될 거리로 반지름을 6으로 설정해줍니다.
그 다음에는 인스펙터 뷰 상단의 레이어에서 Add Layer를 선택하고 Deadbody 레이어를 추가해줍니다.
레이어를 추가한 다음에는 프리팹을 다시 선택하고 프리팹의 레이어를 Deadbody로 설정해줍니다.
그 다음에는 Deadbody 레이어의 콜라이더가 Player 레이어의 콜라이더와 만났을 때만 반응하게 만들어 주기 위해서 상단 메뉴 바에서 [Edit > Project Settings] 항목을 선택해서 프로젝트 세팅 창을 열어줍니다.
그리고 Physics 2D 카테고리의 제일 아래에서 Deadbody 레이어는 Player 레이어에만 반응하도록 만들어줍니다.
콜라이더 세팅이 끝난 다음에는 Deadbody 스크립트를 열어줍니다.
Deadbody 클래스에서는 OnTriggerEnter2D 콜백 함수와 OnTriggerExit2D 콜백 함수를 만들어줍니다.
그리고 감지된 플레이어가 들어오거나 나갈 때마다, 자기 자신이고 유령이 아닌 상태라면 리포트 버튼을 활성화시키거나 비활성화시켜 줘야합니다.
우선 코드를 저장하고 에디터로 돌아갑니다.
그리고 ReportButtonUI라는 이름으로 C# 스크립트를 생성하고 스크립트 에디터를 다시 열어줍니다.
스크립트 에디터가 열리고 나면 스크립트의 상단에 UnityEngine.UI 네임스페이스를 using 선언해줍니다.
그리고 멤버 변수로 Button 타입의 reportButton을 선언해주고 SetInteractable 함수를 만들어서 매개변수인 isInteractable 값에 따라서 버튼을 활성화시키거나 비활성화시키도록 코드를 작성해줍니다.
그 다음에는 IngameUIManager 클래스로 이동해서 ReportButtonUI를 캐싱해서 쉽게 접근할 수 있도록 해줍니다.
캐싱 작업이 끝나면 Deadbody 클래스로 이동해서 OnTriggerEnter2D 콜백 함수에서는 SetInteractable 함수로 리포트 버튼을 활성화 시키게 만들어주고 OnTriggerExit2D 콜백 함수에서는 SetInteractable 함수로 리포트 버튼을 비활성화시키게 만들어줍니다.
코드를 모두 작성한 다음에는 저장하고 에디터로 돌아갑니다.
에디터로 돌아온 다음에는 Report Button을 찾아서 ReportButtonUI 컴포넌트를 붙여주고 프로퍼티를 할당합니다.
그리고 캔버스에 붙어있는 IngameUIManager에 방금 붙여준 ReportButtonUI를 프로퍼티에 할당해줍니다.
그리고 메인 카메라와 All See Camera에서 레이어가 Deadbody인 시체를 보이게 만들기 위해서 두 카메라를 선택하고 Culling Mask에 Deadbody 레이어를 추가합니다.
작업이 끝나면 게임을 빌드합니다.
빌드가 완료되고 게임을 실행해서 테스트해보면 시체가 시야에 잡히기 시작하면 리포트 버튼이 활성화되고 멀어지면 비활성화되는 모습을 볼 수 있습니다.
리포트 UI 배치
그 다음 작업은 신고 버튼을 누른 뒤에 시체 리포트 UI를 띄우는 것입니다.
먼저 영상 하단의 링크에서 작업에서 사용될 리소스 패키지를 다운로드 받아서 임포트합니다.
리소스 임포트가 끝나면 Canvas 아래에 Report UI라는 이름으로 Image 게임오브젝트를 만들고 화면 영역 전체를 덮도록 만들어 줍니다.
그리고 이미지의 알파 값을 0으로 내려서 투명하게 만들어 줍니다.
그 다음에는 그 아래에 이미지 오브젝트를 생성하고 임포트한 스프라이트들을 넣어서 게임의 리포트 UI와 비슷하게 만들어줍니다.
리포트 UI 기능 구현
이미지를 모두 배치한 다음에는 ReportUI라는 이름으로 C# 스크립트를 생성하고 스크립트 에디터를 엽니다.
스크립트 에디터가 열리고 나면 스크립트의 상단에 UnityEngine.UI 네임스페이스를 using 선언해줍니다.
그리고 멤버 변수로 Image 타입의 deadbodyImg와 Material 타입의 material을 선언해줍니다.
그 다음에는 Open 함수를 만들어서 캐릭터가 움직이지 못하게 만든 다음 머티리얼을 인스턴싱해주고 매개변수로 받은 deadbodyColor로 deadbodyImg의 색을 변경하도록 만들어줍니다.
그 다음에는 Close 함수를 만들어서 이 ReportUI를 닫는 기능도 만들어줍니다.
이 다음 단계로는 IngameUIManager 클래스로 이동해서 reportUI에 접근하기 쉽도록 캐싱하는 코드를 작성합니다.
이렇게 ReportUI 클래스의 작업이 끝난 다음에는 버튼을 눌렀을 때 모든 플레이어의 화면에서 리포트 UI가 뜨게 만들어야 합니다.
리포트 UI를 뜨게 만들기 전에 모든 유저에게 알려주기 위해서 발견한 시체의 색을 전달할 필요가 있습니다.
지난 작업에서는 죽어서 유령이 된 플레이어가 투명해지게 만들어줬지만 실제 게임과 다르게 유령 플레이어끼리 서로를 볼 수 없는 상태였습니다.
제일 처음할 작업은 이 문제를 해결해서 유령 플레이어들끼리 보이게 만들어 주는 것입니다.
먼저 IngameCharacterMover 스크립트를 찾아서 열어줍니다.
스크립트 에디터가 열리고 나면 먼저 Dead 함수로 가서 지난 영상에서 빼먹었던 플레이어가 죽은 뒤에 플레이어 타입이 Ghost로 바뀌는 코드를 추가해줍니다.
그 다음에는 SetVisibility 함수를 만들고 매개변수인 isVisible 값에 따라서 캐릭터를 숨기거나 보이게 해주는 코드를 작성합니다.
그리고 RpcDead 함수로 가서 내가 죽지 않은 상태일 때 다른 캐릭터가 죽었다면 투명하게 만들어주는 코드를 이 SetVisibility 함수로 대체해줍니다.
그 다음에는 자기가 죽었을 때 나보다 먼저 죽은 유령 플레이어들을 보이게 만들어줘야 합니다.
그대로 RpcDead 함수에서 내 캐릭터를 유령으로 바꾼 뒤 GameSystme의 GetPlayerList 함수로 플레이어 목록을 가져와서 이미 유령 상태인 플레이어들의 캐릭터를 SetVisibility 함수로 보이게 만들어주는 코드를 작성합니다.
코드를 모두 작성한 다음에는 저장하고 에디터로 돌아가서 게임을 빌드합니다.
빌드가 완료된 다음 테스트해보면 임포스터에게 죽어서 유령이 된 플레이어끼리 서로 볼 수 있게 되는 모습을 확인할 수 있습니다.
유령 플레이어가 벽뚫고 다니게 만들기
두 번째 작업은 유령이 된 플레이어가 장애물에 걸리지 않고 벽을 뚫고 다니게 만들어 주는 것입니다.
이 부분은 간단하게 IngameCharacterMover 클래스로 이동해서 GetComponent 함수로 게임오브젝트에 붙어있는 BoxCollider2D 컴포넌트를 찾아서 비활성화시키게 만들어 줍니다.
코드를 작성하고 저장한 다음 에디터로 돌아가서 게임을 빌드합니다.
빌드가 완료된 다음 실행해서 테스트해보면 유령이 된 플레이어는 자유롭게 벽을 뚫고 다니는 모습을 확인할 수 있습니다.
유령 플레이어의 시야
하지만 벽을 넘어다니다 보면 벽의 그림자가 이상해지는 모습을 볼 수 있습니다.
이런 문제를 제거하고 유령 플레이어의 시야 제한을 없애기 위해서 유령이 된 플레이어의 그림자 세팅을 바꿔주겠습니다.
Hierarchy 뷰를 보면 빛이 닿는 영역을 밝게 하고 그렇지 않은 영역은 어둡게 하기 위한 Shadow Light와 어두운 영역을 보이게 만들어주는 Global Light, 그리고 빛이 닿는 영역에 있는 캐릭터만 보이게 만들기 위해 영역을 구분짓는 Light Map Light가 있는 것을 볼 수 있습니다.
유령이 된 플레이어가 화면 전체를 볼 수 있게 만들어주기 위해서는 Light Map Light의 타입을 Global로 바꾸고 Shadow Light의 Intensity를 0, Global Light의 Intensity를 1로 변경해주면 될 것 같습니다.
우선 GameSystem 스크립트를 찾아서 열어줍니다.
스크립트 에디터가 열리고 나면 스크립트의 상단에 UnityEngine.Experimental.Rendering.Universal 네임스페이스를 using 선언해줍니다.
그리고 Light2D 타입의 shadowLight, lightMapLight, globalLight를 멤버 변수로 선언해줍니다.
그 다음에는 ChangeLightMode 함수를 선언하고 앞에서 이야기 한대로 매개변수로 받은 타입이 Ghost라면 lightMapLight의 lightType을 global로 변경하고 shadowLight의 intensity를 0, globalLight의 intensity를 1로 변경해줍니다.
그 다음에는 IngameCharacterMover의 RpcDead 함수로 이동해서 자신의 캐릭터가 죽은 뒤에 GameSystem의 ChangeLightMode 함수를 호출하도록 만들어줍니다.
코드를 모두 작성한 다음에는 저장하고 에디터로 돌아가서 Game System 오브젝트의 프로퍼티에 각 라이트들을 할당해줍니다.
그리고 작업이 완료되면 게임을 빌드합니다.
빌드가 완료되고 테스트해보면 유령이 된 플레이어는 그림자의 방해없이 모든 곳을 볼 수 있게 된 것을 확인할 수 있습니다.
아웃트로
이번 영상에서는 드디어 기나긴 크루원 킬 기능을 마무리했습니다.
다음 영상부터는 어몽어스의 다른 기능을 만들어보도록 하겠습니다.
이상 베르의 게임 개발 유튜브였습니다. 감사합니다.
타임라인
0:00 인트로
0:15 유령 플레이어끼리 보이게 만들기
1:42 유령 플레이어가 벽 뚫고 다니게 만들기
2:13 유령 플레이어 시야
4:23 아웃트로
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.