
Unity에서 리바인딩 가능한 입력 컨트롤 만들기
요약
Unity의 Input System과 UI Toolkit을 사용하여 플레이어가 키보드와 게임패드 입력을 자유롭게 리매핑할 수 있는 시스템을 구축하는 방법을 다룹니다. 컨트롤 스킴 설정부터 사용자 정의 바인딩의 세션 저장 및 로드 기능까지 구현 과정을 설명합니다.
핵심 포인트
- Unity Input System을 활용한 키보드 및 게임패드 매핑 방법
- UI Toolkit을 이용한 절차적 컨트롤 옵션 메뉴 생성
- 플레이어의 개별 컨트롤 리매핑 기능 구현
- 사용자 정의 바인딩 설정을 세션 간 저장하고 로드하는 법
비디오: Unity에서 리바인딩 가능한 입력 컨트롤 만들기
채널: Game Dev Guide
길이: 18분 46초
출처: 자막 (자동 생성, 영어)
스크립트:
비디오 게임에서 가장 의견이 갈리고 아마도 가장 논쟁이 많은 메뉴 옵션 중 하나는 Y축을 반전시키는 카메라 토글(camera toggle)입니다. 이것이 잠재의식 속에 있는 로그 파이터 조종사의 판타지 때문인지, 아니면 이 도구로 삼각대 헤드를 수년간 돌려온 습관 때문인지는 모르겠지만, 저는 옵션 메뉴에 들어가 카메라를 반전시키지 않고는 물리적으로 게임을 시작할 수 없습니다. 이 메뉴 옵션의 존재와 그 양극화된 성격은 실제로 여러 학술 연구의 주제가 될 정도로 광범위한 관심을 끌어왔습니다. 플레이어가 특정 입력을 눌렀을 때 카메라가 위나 아래를 보게 하는 것처럼 겉보기에는 단순해 보이는 일 말입니다. 그리고 이 문제에 대한 합의가 없다는 점은, 개발자로서 우리가 키보드나 게임패드에 입력을 배치하는 방식만으로도 엄청난 마찰(friction)을 만들어낼 수 있다는 것을 보여줍니다. 따라서 게임플레이 컨트롤이 입력 장치에 어떻게 매핑되는지에 대해 플레이어에게 더 많은 자유를 주는 것이 플레이어에게 더 유연하고 바람직한 결과를 제공할 것이라는 점은 당연해 보입니다. 운이 좋다면 게임패드에서 몇 가지 사전 설정된 컨트롤 스킴(control schemes)을 선택하거나, 버튼을 누르고 있을지 또는 토글할지에 대한 약간의 [음악] 설정을 얻을 수 있을 것입니다. 하지만 우리는 반복해서, 플레이어에게 더 편안하거나 인지적 부담이 적은 위치로 컨트롤을 리매핑(remapping)할 수 있는 유연성을 거의 또는 전혀 제공하지 않는 수많은 게임을 보게 됩니다. 물론 특정 엔진이나 게임이 왜 이렇게 하지 않는지에 대해서는 수많은 이유가 있을 것입니다. 저는 오늘 그 문제를 두고 싸우려는 것이 아닙니다. 하지만 순전히 실수로 누락된 경우라면, 저는 초기 단계부터 리바인딩 가능한 컨트롤(rebindable controls) 지원을 구현할 것을 옹호하기 위해 이 자리에 있습니다. 다행히도, Unity에서 이를 구현하는 것은 여러분이 생각하는 것만큼 복잡하지 않습니다.
그래서 오늘은 키보드와 게임패드(gamepad) 모두에 매핑될 수 있고, 이 둘 사이를 매끄럽게 전환할 수 있을 뿐만 아니라, 플레이어에게 미리 설정된 컨트롤 스킴(control scheme) 중에서 선택하거나 컨트롤 자체를 완전히 리매핑(remap)할 수 있는 옵션을 제공하는 컨트롤 스킴을 구축하는 방법을 살펴보겠습니다. 안녕하세요, 저는 Matt입니다. [music] GameDev Guide에 오신 것을 환영합니다. 이번 에피소드에서는 Unity의 입력 시스템(input system)을 사용하여 일련의 컨트롤을 설정하고, 이를 키보드의 키와 게임패드(gamepad) 모두에 매핑하는 방법을 살펴보겠습니다. 우리는 UI Toolkit을 사용하여 인터페이스를 구축하고, 그 바인딩 시스템(binding system)을 활용하여 컨트롤을 위한 옵션 메뉴를 절차적으로 생성함으로써 [music] 플레이어가 메뉴에서 이를 확인할 수 있도록 할 것입니다. 그런 다음 이러한 컨트롤을 서로 다른 프리셋(preset)으로 교체할 수 있는 방법과, 플레이어가 원하는 키나 버튼으로 개별 컨트롤을 리매핑(remap)할 수 있도록 하는 코드를 작성하는 방법을 살펴보겠습니다. 마지막으로, 사용자 정의 바인딩(custom bindings)이 세션 간에 저장되고 로드되도록 보장할 것입니다. 시작하기 전에, 이 영상의 스폰서인 Odin에 대해 잠시 감사 인사를 전하고 싶습니다. Odin에 대해 들어본 적이 없다면, 이들은 Unity 워크플로우(workflow)를 크게 가속화하는 도구인 Odin Inspector의 제작사입니다. Odin은 수천 줄의 커스텀 에디터(custom editor) 코드를 작성할 필요 없이, 130개 이상의 내장 어트리뷰트(attributes)를 조합하여 인스펙터(inspector)와 에디터(editor)의 모습을 정의함으로써 훨씬 더 쉽게 커스텀 인스펙터를 구축할 수 있게 해줍니다. Odin은 방금 4.0 버전을 출시했으며, 이는 8년 전 Odin이 출시된 이후 이 도구의 가장 큰 업데이트입니다. 이번 업데이트에는 완전히 새로운 비주얼 디자이너(visual designer)가 포함되어 있으며, 드래그 앤 드롭(drag and drop) 인터페이스를 통해 단 한 줄의 코드도 작성하지 않고도 몇 분 만에 고급 커스텀 에디터를 만들 수 있습니다.
[music] 새로운 비주얼 디자이너(visual designer)를 사용하면 버튼을 한 번 클릭하는 것만으로 그룹, 버튼, 속성(attributes) 및 다양한 기타 컴포넌트(components)를 추가할 수 있으며, 비주얼 디자이너 창 내에서 모든 것을 설정할 수 있습니다. 비주얼 디자이너를 통해 이루어진 모든 설정은 사람이 읽을 수 있는 별도의 파일로 저장되므로, 모든 커스텀 에디터(custom editors)와 툴링(tooling)을 프로젝트 코드와 완전히 분리된 상태로 유지할 수 있습니다. 이는 엄청난 시간을 절약해 줄 뿐만 아니라, 모든 에디터 툴을 매우 확장 가능하고 유지보수하기 쉽게 만들어 줍니다. 또한 비주얼 디자이너를 통해 이제 프로그래머가 아닌 사람들도 안전하게 에디터 툴을 생성하고 미세 조정할 수 있어, 엔지니어들이 게임에서 가장 중요한 부분에 집중할 수 있도록 리소스를 확보해 줍니다. 그리고 빠른 프로토타이핑(prototyping)과 반복적인 툴 구축에도 매우 좋습니다. 만약 Odin Inspector와 새로운 비주얼 디자이너 워크플로(workflow)가 마음에 드신다면, 아래 설명란의 링크를 사용하거나 지금 화면의 QR 코드를 스캔하여 직접 구매해 보세요. Odin의 개인 라이선스는 일회성 구매 방식이며, 아무런 조건 없이 완전히 무료로 모든 기능을 사용할 수 있는 3개월 체험판을 제공합니다. 영상을 후원해 주신 Odin 측에 진심으로 감사드립니다. 자, 그럼 이제 컨트롤을 리바인딩(rebinding)하는 단계로 넘어가 볼까요? 보시는 것처럼, 저는 여기서 아스테로이드(asteroids) 스타일의 작은 2D 게임을 만들고 있습니다. 현재 우주선은 그저 우주를 관찰하며 공허를 지나가는 근처의 암석들에 의해 파괴되고 있는 상태입니다. 그래서 저는 이것을 실제로 게임으로 바꾸고 우주선에게 싸울 기회를 주고 싶습니다. 그렇게 하려면 몇 가지 입력 액션(input actions)을 설정하고 이를 우주선 컨트롤러(spaceship controller)에 매핑하여 플레이어가 날아다닐 수 있도록 해야 합니다. 저는 이 프로젝트를 Unity의 2D URP 템플릿을 사용하여 만들었는데, 보시는 바와 같이 미리 정의된 입력 액션 세트가 포함되어 있습니다. 따라서 이를 시작점으로 사용하겠습니다. 이것을 'base actions'와 같이 간단한 이름으로 변경하겠습니다. [music] 안으로 들어가서 여기 있는 대부분의 액션들을 제거하고, move, attack은 유지하며, 이 항목의 이름은 boost로 변경하겠습니다. 그런 다음 에셋(asset)을 저장하겠습니다.
[music]
나중에 몇 가지 동작(actions)을 추가할 수 있겠지만, 지금은 이 정도면 충분할 것입니다. 여기를 살펴보면, 우리의 키들이 처음에 어떻게 매핑(mapped)되어 있는지 볼 수 있습니다. 우리의 move는 게임패드(gamepad)의 왼쪽 스틱(left stick)과 키보드의 WASD에 매핑되어 있습니다. 우리의 attack은 마우스 왼쪽 버튼 또는 키보드의 Enter에 매핑되어 있습니다. Enter는 조금 어색하네요. 그러니 이것을 Space 키로 바꿉시다. 그리고 우리의 boost의 경우, 키보드에서는 Shift가 괜찮지만, 게임패드에서는 아마 트리거(trigger) 중 하나여야 할 것입니다. 그러니 오른쪽 트리거(right trigger)로 설정하겠습니다. 그리고 실제로, 게임패드의 fire를 West 대신 South 버튼으로 바꿉시다.
[music] 이것은 좋은 초기 컨트롤 세트입니다. 이제 우리의 함선 컨트롤러(ship controller)를 이 입력(inputs)들에 연결해 보겠습니다. 우리의 함선에 Player Input 컴포넌트(component)를 추가하겠습니다. 보시다시피, 이것은 우리의 동작(actions)들을 자동으로 할당할 것입니다. 그리고 여기에 작은 경고가 뜨네요. 그러니 프로젝트 설정(project settings)으로 가서 전역적으로(globally) 제거하겠습니다. [music]
또한 우리의 기본 스킴(default scheme)을 키보드와 마우스(keyboard and mouse)로 설정하고, 기본 맵(default map)을 player로 설정하겠습니다. 이것은 메시지 전송(send messages) 방식으로 설정되어 있으므로, 컨트롤러의 메서드(methods)를 사용하여 이러한 입력들을 캡처할 수 있습니다.
[music] 따라서 함선 컨트롤러에 각각에 대한 메서드를 추가하겠습니다. 보시는 바와 같이, 이제 키보드나 마우스 버튼이 [music] 눌렸을 때 이러한 입력 이벤트(input events)를 받게 됩니다. 그럼 이것들을 설정해 봅시다. move 액션(action)으로부터 입력을 가져와 두 개의 float 값으로 분리하겠습니다. 저는 회전(turning)이 상당히 결정론적(deterministic)이기를 원하므로, 단순한 고정값으로 유지하고 업데이트 루프(update loop)에서 회전을 처리하겠습니다. 함선이 씬(scene)에 있는 물리 객체(physics objects)에 반응하기를 원하지만, 너무 압도적이지는 않기를 바랍니다. 그래서 우리가 회전할 때, 우리가 얻었을지도 모를 모든 각속도(angular velocity)를 줄이도록 하겠습니다. 일반적으로 이것은 개인적인 선호의 문제인데, 저는 플레이어의 회전을 처리하기 위해 물리(physics)에 의존하는 것을 별로 좋아하지 않기 때문입니다. 저는 회전이 반응성(responsive) 있게 느껴지는 것을 훨씬 더 선호합니다. 그것이 바로 우리가 여기서 회전을 직접 제어하는 이유입니다.
전진 이동을 위해, 별도의 메서드를 추가하고 상대적인 힘(relative force)을 사용하여 오브젝트가 현재 바라보고 있는 방향으로 속도(velocity)를 더해줄 것입니다. [music] 만약 플레이어가 아래쪽 입력(down input)을 사용한다면, 플레이어가 멈출 때까지 입력에 따라 선형 속도(linear velocity)를 줄임으로써 이를 일종의 브레이크(break)로 작동하게 할 것입니다. [music] 보시다시피, 이제 우리 함선에 꽤 괜찮은 물리 컨트롤러(physics controller)가 생겼습니다. 우주 장면(space scene)에 어울릴 만큼 부유감이 있으면서도, 장애물을 쉽게 피해 다닐 수 있을 정도로 반응성(responsive)이 좋습니다. 이제 우리의 발사(shoot) 메커니즘을 사용해 봅시다. [music] 액션(actions)이 작동하는 방식 때문에, 버튼(buttons)으로 설정된 경우 버튼이 눌렸을 때 단 한 번의 이벤트만 발생합니다. [music] 하지만 스페이스 키를 계속해서 누르고 싶지는 않을 것입니다. 그래서 발사 액션(fire action)을 버튼에서 값(value) 타입으로 업데이트하여, [music] 버튼을 떼는 것을 감지할 수 있도록 하고자 합니다. 이제 on attack 메서드에서 값이 0보다 큰지 확인하고, 함선에 발사 명령을 내릴 불리언(boolean) 값을 할당할 수 있습니다. update 메서드의 하단에, 발사 중이라면 총알을 생성(spawn)하는 메서드를 추가할 수 있습니다. 여기에서 우리는 새로운 총알을 생성하고, 함선의 트랜스폼(transform) 및 방향에 맞춰 함선의 약간 앞쪽에 배치할 것입니다. 또한 버튼을 누르고 있는 동안 매 프레임마다 총알이 생성되지 않도록, 액션에 약간의 쿨다운(cool down)을 줄 것입니다.
총알 자체는 매우 간단합니다. 캡슐 콜라이더(capsule collider)와 리지드바디(rigid body)가 포함된 작은 스프라이트(sprite)일 뿐입니다.
총알이 생성되면, 바라보는 방향으로 지속적인 속도(continuous velocity)를 더해주고, [music] 무언가에 부딪히거나 약 3초 이상 유지될 경우 파괴(destroy)합니다.
이로써 우리의 게임이 완성되어 가고 있습니다. 우리는 비행하며 소행성(asteroids)을 쏘아 점진적으로 파괴할 수 있습니다. 보시다시피, 총알이 무언가에 부딪힐 때마다 생성되는 VFX 요소와 소행성이 폭발할 때의 효과들도 추가했습니다. 마지막으로, 부스트(boost) 메커니즘을 추가해 봅시다.
이전과 마찬가지로, 버튼에서 부스트(boost) 키를 값(value)으로 설정하는 것부터 시작하겠습니다. 이렇게 하면 부스트 키가 눌렸는지 또는 떼졌는지 여부를 감지할 수 있으며, 이를 통해 부스트 중인지 여부를 결정할 수 있습니다. 그런 다음 이 값을 사용하여 함선에 배치한 루핑 효과(looping effects)를 시작하거나 중지할 수 있습니다.
[music]
다음으로, 부스트를 처리할 메서드(method)를 추가하겠습니다. 저는 부스트가 갑작스러운 힘의 분출처럼 느껴지기를 원합니다. 그래서 최대 부스트 속도(maximum boost velocity)를 위한 새로운 값을 정의할 것입니다. 그리고 부스트 메서드 내에서 우리가 부스트 중인지, 그리고 최대치(cap)에 도달했는지 여부를 확인하겠습니다. 그런 다음 부스트 버튼이 눌려 있는 동안에는 전방 힘(forward force)을 한 번에 추가할 것입니다. 만약 눌려 있지 않다면, 속도를 최대 속도(maximum velocity)로 빠르게 줄일 것입니다.
기본 최대 속도를 약간 낮추고 부스트를 더 의미 있게 만들기 위해 함선의 값들을 약간 조정하고 싶을 것입니다. 이제 우리는 조금 더 곡예를 부리듯 작은 함선을 환경 곳곳으로 부스트하며 움직일 수 있습니다. 플레이어가 UI 메뉴를 통해 사용 가능한 컨트롤을 확인할 수 있다면 정말 좋을 것 같습니다. 그러니 메뉴를 하나 설정해 봅시다. 먼저, 플레이어가 메뉴에 접근할 수 있도록 새로운 액션(action)을 추가하겠습니다. 액션 에셋(actions asset)으로 가서 'menu'라는 이름의 새로운 액션을 추가합니다. 이 경우에는 버튼이 눌렸을 때만 알면 되므로 액션 타입(action type)을 버튼(button)으로 남겨두어도 괜찮습니다. 여기에서 키보드의 Escape 키에 대한 바인딩(binding)을 추가하고, 게임패드(gamepad)의 Select 키에 대한 바인딩도 추가하겠습니다.
먼저 씬(scene)에 새로운 UI Document를 생성하겠습니다. 그런 다음 UI Builder를 열고 'menu'라는 이름의 새로운 UXML 파일과 새로운 USS 파일을 생성합니다. 여기에서 새로운 루트 비주얼 엘리먼트(root visual element)를 추가하고 기본적인 투명한 검은색 배경을 할당하겠습니다. 이 패널의 이름을 'panel'이라고 짓겠습니다. 저는 모든 스타일 정보를 UXML에 인라인(inline)으로 넣기보다 셀렉터(selector)에 묶어두는 것을 좋아합니다. 따라서 'panel-background'라는 새로운 스타일을 추가하고 'Extract Inline Styles to New Class'를 선택하겠습니다.
그다음, 'window'라고 부를 또 다른 시각적 요소(visual element)를 추가하겠습니다. 이곳은 메뉴의 대부분의 콘텐츠가 들어갈 공간이 될 것입니다. 따라서 불투명한 회색 배경을 추가해 보겠습니다. 그리고 배경 뒤로 게임 화면이 어느 정도 보일 수 있도록 약간의 마진(margin)도 주겠습니다. 그런 다음 이 부분을 [music] 셀렉터(selector)로도 추출하겠습니다.
여기 계층 구조(hierarchy)에서 이 클래스 리스트 뷰(class list view)도 켜겠습니다. UI 도큐먼트(UI document) 요소들을 보여주거나 숨길 수 있게 하고 싶기 때문입니다. 따라서 창 전체의 다양한 요소에 적용할 수 있는 'hidden'이라는 새로운 셀렉터를 만들겠습니다. 그리고 이를 여기 루트 패널(root panel) 요소에 적용하겠습니다.
그다음, 새로운 메뉴를 UI 도큐먼트에 할당하겠습니다. 그리고 UI에 매니저 역할을 할 스크립트를 만들겠습니다. 이것은 메뉴 버튼이 눌렸을 때 우리의 ship에서 호출할 싱글톤 인스턴스(singleton instance)가 될 것입니다.
[music]
현재 우리의 모든 입력 이벤트(input events)는 플레이어 컨트롤러(player controller)에서 직접 제어되고 있습니다. B
AI 자동 생성 콘텐츠
본 콘텐츠는 YouTube Game Dev Guide의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기