=== Prologue ===
작심 3일이라는 말이 있지만 2주 차를 넘어선 월간 TECH
스스로 칭찬하고 뿌듯하다.
사이드 프로젝트라 시간이 날까 했었는데 또 하고자 하는 마음이 있으면 시간이 나게 된다.
지난주 로블록스 서버 터짐 사건으로..!
어떻게 되나 걱정했었는데 월요일 아침 복구되었다는 로블록스 공식 트위터 계정을 보고 안심했다.
지난 포스팅에도 말했듯이 이번주는 스크립트(기능적인) 부분을 찾아보고 적용시키기로 했다.
로블록스에 관련된 기능을 찾다가 한 블로그를 발견했다.
로블록스에는 공식문서가 있는데 그 공식문서를 보고 해석한, 하지만 블로그 주인의 의견과 해설이 들어간 글들이었다.
튜토리얼 마냥 있어서 (기초) 부터 (중급)까지 처음 접하는 나에게는 더 읽기 쉽고 이해가 쉬울 것 같았다.
==== Mission ====
이번주는 아래 블로그에 있는 튜토리얼을 읽고 어떤 식으로 [빨간 마스크] 게임에 적용시킬 수 있을지,
플레이어는 어떻게 움직이고 빨간마스크는 어떻게 동작하는지 등등을 익히기로 한다.
https://robloxtrip.tistory.com/
=== description ===
내가 먼저 생각해보고 필요할때마다 찾아서 스크립트나 움직임을 변형할 수 있지만,
로블록스나 루아문법에 대해 아무런 정보가 없는 상태에서는 생각하기 어렵다.
그렇기 때문에 남들이 짜 놓은 스크립트나 어떤 식으로 진행시키는지 먼저 알고 나면 큰 틀이 잡히는 것 같다.
필자는 먼저 큰 범주로 어떻게 흘러가는지를 조사하는 방식이라면 (넓게)
개발자 야잴씨는 몬스터를 불러와서 그 스크립트 하나를 분석하는 방식으로 (깊게) 로블록스를 파헤치고 있었다.
==== detail progress ====
필자는 이런식으로 정리하면서 알아갔다. 아래는 내가 메모장에 정리한 내용들이다. (블로그의 내용이나 필요한 내용만 추출했다고 보면 된다.)
1. 블로그 하나하나를 읽으면서 함수나 속성등 필요한 게 있다면 정리했다.
2. 어떤 움직임 or 기능이 있는지 숙지했다.
3. 로블록스에 관한 전반적 이해를 했다.
(어떤 식으로 구성되어있는지, 꿀팁 또는 주의사항 등)
필요한 스크립트 <기초>
다만, 게임요소를 생성하고 없애는 작업은 생각보다 리소스를 많이 잡아먹는다. 이런 방식은 실전 게임에서는 사용할 수 없다. 실제 게임 제작은 항상 퍼포먼스를 신경 써줘야 한다. 그래서 실제로 없애고 생성하는 방식이 아니라, 블록이 보이지 않게 해주는 방식을 사용하자.
◆ 블럭이 사라졌다가 나타나게 하기
Part에는 투명도(Transparency)라는 속성이 있는데 투명도는 기본 0으로써, 1에 가까워질수록 투명해지다가 1이 되면 아예 투명해진다.
◆ 아바타를 죽이는 기능
모든 Part에는 Touched라는 이벤트가 존재하는데, 이 이벤트는 게임중에 다른 게임 오브젝트가 닿았을 때 자동으로 발생한다. killPlayer() 함수를 선언하고 Touched 이벤트와 연결하면, Touched 이벤트가 발생할 때 killPlayer() 함수를 호출한다.
KillPlayer로 이름을 바꾸자. 이 블럭에 닿으면 게임 아바타를 죽이는 기능이 들어있는 스크립트이다.
** KillPlayer는 함수명
◆ 블럭이 옅어지다가 사라지는 기능
(for 문사용 ) - lua
Transparency를 천천히 1-10까지 돌아가면서 준다.
wait(0.1) 정도 함수도 같이 적용
Touched 이벤트의 연속 발생 자체를 막는 것은 어렵다. 그렇다면 이벤트에 연결된 fade() 함수의 연속 실행을 방지하면 된다. 그러기 위해서 변수를 하나 사용하자.
◆ 점수를 화면에서 보여지게 만들기
- 게임 시작하고 나면 자동으로 1초마다 각 플레이어들의 점수를 계속 올려준다. 게임이 시작될 때 자동으로 시작될 서버 스크립트는 ServerScriptService에 자식으로 추가하면 된다. 탐색기에서 ServerScriptService를 찾아서 스크립트를 추가하고 SetupPoints라고 이름을 바꾸자.
- 로블록스에서 "서비스(Service)"는 다양하고 유용한 기능을 수행하는 객체이다. 이 객체를 통해 여러 가지를 할 수 있는데 여기서 우리는 Players라는 서비스를 통해 각 플레이어들이 게임에 입장했다는 이벤트를 받는 기능을 사용한다.
** 오브젝트의 복제는 간편하다. 다만, 각 FadingPlatform의 스크립트들도 다 같이 복제가 된다. 그 말은 똑같은 기능을 하는 스크립트들이 오브젝트 수만큼 존재한다는 말이다. 리소스의 낭비도 문제지만 만일, 스크립트에 버그가 발생하여 수정을 해야 한다고 가정해보자. 하나만 고쳐서는 안 되고 FadingPlatform의 수만큼의 스크립트를 다 고쳐줘야 한다. 결론적으로 이런 방식으로 오브젝트를 복제해서는 안된다. 안되지만, 여기는 튜토리얼이므로 그냥 그렇게 사용한다. 중급 튜토리얼에서 여러 오브젝트에 사용되는 스크립트를 어떻게 관리할 지에 관련된 튜토리얼이 있다. 참고하자.
[다수의 똑같은 스크립트의 존재는 리소스의 낭비라는 측면도 있고, 버그때문에 혹은 기능 추가 삭제를 위해서 소스를 수정하기 했을 때... 모든 스크립트를 똑같이 다 수정해 줘야 한다.]
** 지금껏 게임 스크립트들은 그냥 게임 오브젝트에 추가시켜서 게임 오브젝트가 로드될 때 실행되는 형태였었다. 하지만, 플레이어 점수같은 플레이어의 상태를 변경하는 소스 코드는 서버에서 실행되는 것이 가장 좋다.
왜 서버에서 실행되야 좋을까?
여러 플레이어들과 함께 즐기는 게임이 기본인 로블록스 게임에서는 기본적으로 서버와 여러 클라이언트와의 긴밀하게 연결되어 있다. 점수와 같이 게임에 핵심적인 요소는 서버에서 변경하고 각 플레이어들에게 보여주는 구조가 심플하고 이해가 빠르며 안정적일 것이다.
** 로블록스는 서버-클라이언트 모델을 사용
◆ 플레이어의 이벤트를 기다리는 서버
Players서비스에서는 플레이어 입장 시에 PlayerAdded라는 이벤트를 발생시킨다. 이 이벤트에 onPlayerAdded라는 함수를 연결하여 해당 플레이어의 점수를 초기화하는 기능을 코딩하자.
로블록스에서 서비스는 어디에서든 game 오브젝트의 GetService() 함수를 사용하여 얻어 낼 수 있다. 싱글레톤 패톤처럼 어디서든 원하는 곳에서 사용한다. game 오브젝트는 게임에 필요한 거의 모든 것들을 포함하고 있으므로 자주 접하게 될 것이다.
◆ leaderstats 폴더 만들기
리더보드에 플레이어의 점수를 보여주기 위해서 할 일은 player 객체에 새로운 Folder를 만들어서 추가해주는 것이다. Folder는 로블록스 객체들을 담아서 모아주는 컨테이너 역할을 한다. 우선, player 객체에 leaderstats라는 이름의 Folder를 추가하고 그 폴더 안에 우리가 넣고 싶은 점수를 IntValue 형태로 집어넣으면 된다.
** 여기서 폴더의 이름은 정확하게 leaderstats 만 사용해야 한다. 지금 사용하는 리더보드는 로블록스가 자체적으로 제공하는 것이다.
◆ IntValue 데이터형
Int데이터형을 저장하는 객체이다. Changed 이벤트를 가지고 있어서 IntValue 객체의 값이 변경될 때마다 이벤트를 발생시켜 준다는 점이다. 아무튼, leaderstats폴더에 우리는 점수값을 넣을 것이므로 IntValue의 이름(Name)은 "Points"라고 하고 값(Value)은 0으로 하자.
◆ 플레이어가 죽었는지 알아내기
하지만, 이번에는 WaitForChild() 함수를 사용할 것이다. player 객체의 캐릭터 모델은 플레이어가 스폰이 된 후에 차례로 구성 요소들이 로드가 된다. 속도가 좀 느린 컴퓨터에서 확인해보면 캐릭터의 생성이 팔 다리 몸통... 하나씩 생성됨을 볼 수 있다. 즉, 플레이어를 스폰한 후 캐릭터 모델을 구성하게 되므로 휴머노이드 객체가 생성되었는지 아직인지는 현 상황에서는 알 수가 없다. 그래서 휴머노이드 객체가 생성될 때까지 기다리고 반환하는 WaitForChild() 함수를 사용한다.
◆ 플레이어 상태 체크하기
lua언어의 또다른 특징인 객체에 attribute(속성)를 추가하는 방법을 사용할 것이다. player객체에 SetAttribute() 함수를 사용하여 IsAlive라는 attribute를 끼어 넣을 수 있게 된다.
<중급>
로블록스 게임중에 게임 상태를 저장하고 읽어오는 방법에 대한 튜토리얼
◆ 로블록스 스튜디오에서 접근 허용하기
기본적으로 로블록스 스튜디오에서 로블록스 서버에 데이터를 저장하고 로드를 허용하지 않는다. 스튜디오에서 테스트를 하기 위해서는 세팅에서 활성화를 시켜줘야 한다. 우선 해당 게임을 로블록스 서버로 배포를 해 놓은 상태에서 아래의 게임 세팅에서 Security 탭에서 API 서비스에 접근을 허용해주자.
◆ DataStoreService 사용하기
로블록스에서 게임 데이터를 저장/로드를 하기 위해서는 DataStoreService 서비스를 사용한다.
◆ (스코어바 만들기 - GUI 라벨 다루기)
- 이미지 추가
로블록스 GUI에서 이미지는 ImageLabel이라는 객체를 사용한다. 스코어 바 프레임에 ImageLabel 객체를 추가한다.
- 텍스트 추가
◆ 가까이 가면 나오는 GUI - Proximity Prompts
레이어가 충분히 가까이 다가가면 "Open"이라는 버튼이 나오거나 설명이 나오는 식의 GUI
◆ 파트에 붙어 있는 GUI 구현
◆ 자연스럽게 열리는 문 만들기
constraint는 두 개의 attachment를 연결해서 특정한 방식으로 움직이게 해주는 역할을 한다. 이 도어에서는 사용할 Constraint는 HingeConstraint
- HingeConstraint의 속성중에서 LimitsEnabled을 찾아서 활성화 : 도어의 꺾임 제한
◆ 관람차 만들기
주목할 점은 현실에서와는 다르게 단 한쪽의 constraint를 사용하여 모터로 사용하였다. 3D 게임은 현실처럼 보이는 게 중요하지 사실 현실은 아니다. 많은 constraint의 사용은 게임을 느리게 만들 수 있으므로 되도록이면 적은 수의 constraint를 사용해야 한다. 리소스는 가능하면 적게 사용하는 것이 끊기지 않는 게임을 만드는데 중요하다.
◆ Tool 오브젝트 저장
플레이어가 돌아다니다가 주워서 장착할 수 있는 아이템인 것이다. 플레이어가 장착하게 되면 이 아이템의 Hot Bar에 표시된다.
◆ Starter Tool
탐색기창에서 Blaster를 드래그하여 StartPack 의 자식으로 옮기자.
◆ Tool 오브젝트의 속성들
- Position / Orientation
- 툴 오브젝트는 대표적으로 Equipped, Unequipped, Activated라는 세 가지의 이벤트를 가지고 있다. 각각 이벤트에 대해 설명하자면,
Equipped 이벤트 : 툴이 캐릭터에 장착될 때 발생
Unequipped 이벤트 : 캐릭터에 장착된 툴이 해제될 때 발생
Activated 이벤트 : 툴이 동작될 때 발생. 예> Blaster에 레이저가 발사될 때. 장착하고 마우스 왼쪽 클릭으로 발사된다.
이 이벤트은 모두 LocalScript에서만 동작한다.
◆ 로블록스 파티클 시스템의 기본
- Particle Emitters
◆ Beam 오브젝트로 레이저 효과
- 포스필드, 폭포의 물줄기, 그리고 레이저 빔을 표현
◆ 파티클로 전기충격 효과
Emit() Plugin이라는 플러그인이다. 이 프로그램을 설치해야 된다. 해당 플러그인 설치 주소로 이동하고 Install 하자.
◆ 커스텀 필터 사용하기(Post-Processing Effect)
- 따뜻한 느낌을 준다거나 차가운 느낌을 주거나, 모자이크 처리를 하거나 색상을 변하게 하는 등의 여러 필터가 있는 것을 알고 있을 것이다. 로블록스에서도 게임 화면에 필터를 적용시켜서 다양한 효과를 줄 수 있다.
- Color Correction 효과 : 화면 색상의 채도, 틴트, 색상 대비등의 효과를 보여준다. 화면의 무드를 바꿔준다거나 자연경관을 강조할 때 사용하면 좋다. 대미지를 입을 때, 화면 전체를 빨간색 틴트로 효과를 주는 것도 좋은 사용법이다.
- Depth of Field 효과 : Deapth of Field 효과는 멀리 있는 것은 흐릿하게하고 가까이 있는 것은 또렷하게 보이는 효과 등을 나타낼 때 사용된다. 포커스가 있는 곳은 선명하게 보여주고 포커스가 없는 곳은 흐릿하게 보여준다.
- 로블록스의 게임을 제작할 때, 보다 현실적인 배경, 환경을 만들고 싶다면 Atmosphere 오브젝트를 알아 두면 좋다. Atmosphere 오브젝트는 공기 중의 입자.. 안개나 황사, 저녁의 노을, 해 뜰 때의 장관 등을 표현하고 싶을 때 사용된다.
◆ 음악 업로드하기
음악을 직접 로블록스에 업로드하는 방식은 안타깝게 로블록스에 로벅스(로블록스의 가상화폐)가 아주 쪼금 필요하다.
해당 링크 Create Audio 타고 페이지를 열어보면 음악을 업로드할 수 있는 페이지가 나온다. 음악을 올리고 나면 자신의 음악 리스트가 나오는데 원하는 음악을 선택하면 나오는 URL에서 숫자가 음악의 ID가 된다. 그 ID를 복사하면 사용할 수 있다.
https://www.roblox.com/library/1837849285/Night-Vision
◆ CFrame 이해하기
- Coordinate Frame의 줄임말인 CFrame은 파트나 모델의 위치와 방향을 알려주는 데이타형이다. 위치(Position)는 x축, y축, z축의 넘버, 그리고 방향(rotation)은 x축, y축, z 축, 각축의 회전 값을 포함한다. 게임 내에서 CFrame 데이터형은 단순히 위치와 방향의 데이터 값만 제공하는 것이 아니라 여러 유용한 프로퍼티와 함수를 제공한다.
- CFrame의 new()함수를 사용하면 생성되는 파트나 모델의 위치를 직접 지정할 수 있다.
◆ 폭발 이펙트(Explosion effects)
휴머노이드는 캐릭터 모델의 목 관절이 부러지면서 폭발로 사망합니다. 포스 필드에 의해 보호되는 모든 파트는 폭발로부터 보호되는데 이 말은 파트의 관절이 부러지지 않아서 휴머노이드가 죽지 않게 된다는 말이다.
만약에 개발자가 관절을 부러뜨리지 않고 어떤 공식에 의해서 휴머노이드에게 데미지를 주고 싶다면, Explosion.DestoryJointRadiusPercent를 0으로 설정하고 Explosion.Hit 이벤트를 사용하여 폭발의 결과를 코드로 처리하면 된다.
FindFirstAncestorOfClass() 함수를 사용하자. 약간 이해가 필요한 함수이다. 인스턴스의 함수인 FindFirstAncestorOfClass() 함수는 인자로 주어진 클래스 이름을 가지고 같은 클래스 이름을 가지는 상위 노드를 찾아서 윗방향으로 찾아서 올라간다.
◆ 이벤트 처리하기
로블록스에서는 기본적으로 콜백 처리를 수행하기 위한 방식으로 이벤트를 사용한다. 버튼을 클릭하거나 특별한 일이 게임내에 일어났을 때, 유저가 게임에 접속했을 때 등등에서도 이벤트를 통해 처리된다. 그리고 서버 클라이언트와의 통신에서도 이벤트를 사용하게 된다.
◆ 함수에 연결하는 방식
Connect() 함수는 해당 이벤트와 특정 함수를 연결해준다. 함수에 연결되는 이벤트는 이벤트가 발생할 때마다 함수가 호출된다.
◆ 이벤트와 함수의 연결 끊기
연결을 끊는 방법은 연결 객체의 Disconnect() 함수를 이용한다.
◆ 클라이언트 스크립트(Local Script) 와 서버 스크립트(Script)
서버 스크립트는 게임 로직같은 것, 게임 진행 상태 저장, 점수 업데이트, 아이템 관련, 블록 생성 같은 모든 유저가 공유해야 하는 정보를 담당한다.
로컬 스크립트( LocalScript) 는 모든 유저가 공유 안 해도 되는 것, 버튼이 눌러졌나 안됐나 같은 류를 담당한다.
RemoteEvent는 서버와 클라이언트간에 단방향 메시지를 제공한다.
RemoteFunction은 클라이언트와 서버가 서로 통신하는 상황에서 사용된다.
Replicated Storage 서비스내의 객체들은 서버 스크립트와 로컬 스크립트 양쪽에서 접근이 가능하다는 특징이 있다.
◆ 성공하는 게임 디자인
개발자인 당신이 관심을 가져야 할 것은 게임을 아름답게 보이게 하는 것이 아니라, 전반적인 게임의 밸런스에 집중해야 한다. "모든 계란을 한 바구니에 담지 마세요"라는 표현을 생각해보자. 한쪽에 치우친 게임은 밸런스가 무너진다.
위의 세 가지 게임은 스타일이 완전히 다른 게임이다. Jailbreak는 세계를 탐험하고 다른 플레이어와 상호 작용하는 것이 주요 기능인 롤플레잉 게임dl다. 따라서 개발자는 플레이어가 상호 작용할 수 있는 거대한 세계가 필요했다. 반면, Bad Business는 레벨 디자인이 게임 플레이를 중심으로 하는 1인칭 슈팅 게임입니다. 1인칭 슈팅 게임은 플레이어가 총에 맞지 않도록 쉽고 빠르게 지도를 돌아다닐 수 있도록 다양한 경로가 필요하다. Roses는 스토리 중심의 공포 게임이므로 A 지점에서 B 지점까지 이벤트와 풍경을 중심에 두는 매우 선형적인 레벨 디자인을 가지고 있다.
항상 보상이 있다는 느낌을 주는 게임으로 만들어라.
어떤 게임을 만들고 싶은지 생각하자. 핵심 역학은 무엇인가? 이것에 초점을 맞춰서 만들고 그 후에 다른 게임요소들(모델링, 프로그래밍, 분위기 등)을 고려하자.
항상 게임을 접근 가능하고 단순하게 만드는 것을 목표로 하자. 많은 배경지식, 혹은 긴 튜토리얼 같은 건 필요없다. 플레이어가 바로 뛰어들어 플레이를 시작할 수 있는 게임을 만드는 것을 의미한다. Tower Defense Simulator나 Tower of Hell과 같은 게임을 참고하자. 마스터할 가치가 있는 게임을 만들면 플레이어에게 성취감을 느끼게 할 수 있다.
개발자 야잴씨는 플러그인에 대해서 정리를 했다고 한다.
==== Result ====
🌵 마을을 꾸미려고 했는데 이론을 중점적으로 공부하다 보니 시각적으로 남는 결과물은 없었다.
🌵 그래도 문서를 읽다 보니 머리에 남는 것과 어떻게 해야 할지 방향이 잡혔다.
🌵 생각보다 빨간마스크프로젝트가 길어질 것 같다.
🌵 2주면 완성할줄알았던, 일정이었지만 사실상 제로 0에서 시작했기 때문에 배우고 익히는 시간이 더 컸다.
🌵 일정이라는것은 모든 것을 다 아는 상태에서 잡는 것이라고 개발자 야잴씨가 말했다.
일정에 지나치게 목매게 된다면, 결국 압박으로 스트레스만 남을 것이라는 의견이다.
그러고 보니
나또한 회사에서 약 3-4일 만에 한 사이트 전체를 오픈해야 한다며 압박에 시달린 적이 있었는데
속도는 났지만 퀄리티는 현저하게 떨어졌었다.
🌵 지금은 조금 더 깊게, 퀄리티를 올리면서 가야 할 때인 거 같다.
최대한 맞추되 현실적인 상황을 고려해서 (본업이 있기에) "무조건 이때까지"라는 틀을 조금은 내려두기로 했다.
개발자야잴씨의
우선 숙지를 하게 되면 생각보다 다음 본격적으로 하게 될 로블록스 "헬스장" 게임은 더 빠르게 진행될 수도 있다는 말에 동의했다.
조급하게 생각하지 말자!
다음 주 일정은
✔ 빨간마스크 스토리 라인을 조금 더 구체화시켜 짜 보기로 한다.
✔ 플레이어의 움직임 스크립트를 직접 코딩해보기로 한다.
✔ 다른 게임을 보며 자연스러운 게임 세계관을 익히기로 한다.
까지로 스스로 정리했다.
너무 너무 잘하고 싶은 마음도, 빨리 완성하고 싶은 마음도 크지만
잘 정리해놓고, 익히고 내 것으로 만들어야 진짜인 법!
천천히 빠르게 가야겠다고 생각한 주차였다.
==== Reference====
📌 로블록스 개발여행이라는 블로그를 참고하였습니다. (로블록스 공식문서 한글 버전 해설)
==== See More ====
🧐 로블록스 "빨간 마스크" 게임 제작기에 대한 개발자야잴씨의 테크 일지가 궁금하다면?
https://jaylee222.github.io/tech/2111072002/
🧐 로블록스 "빨간 마스크" 게임 제작기가 궁금하다면?
https://bokartstudio.tistory.com/68
'NOTE > TECH PROJECT' 카테고리의 다른 글
[월간TECH프로젝트] 로블록스 "빨간마스크" 게임 제작기 4주차 (2) | 2021.11.29 |
---|---|
[월간TECH프로젝트] 로블록스 "빨간마스크" 게임 제작기 3주차 (2) | 2021.11.15 |
[월간TECH프로젝트] 로블록스 "몬스터 Bloody Ghost Girl" 스크립트 분석기 (2) | 2021.11.08 |
[월간TECH프로젝트] 로블록스 "빨간마스크" 게임 제작기 1주차 (2) | 2021.11.01 |
[월간TECH프로젝트] 머지않아 대단한 회사가 탄생할 수도 있다. (0) | 2021.10.30 |