비활성화의 영향 오브젝트 비활성화 (SetActive(false)): 오브젝트와 모든 하위 오브젝트가 비활성화됩니다. Update(), FixedUpdate() 등은 더 이상 호출되지 않습니다. 렌더링(화면 출력)도 멈춥니다.
컴포넌트 비활성화 (enabled = false): 해당 컴포넌트만 비활성화됩니다. 다른 컴포넌트(예: Transform)는 여전히 작동합니다.
예제: 적 캐릭터 등장/퇴장
public GameObject enemy;
void Start()
{
enemy.SetActive(false); // 처음에는 적을 비활성화
}
void Update()
{
if (Input.GetKeyDown(KeyCode.E)) // 'E'를 누르면
{
enemy.SetActive(true); // 적 활성화
Debug.Log("적이 등장했습니다!");
}
}
예제: 적 죽음 처리
void KillEnemy()
{
gameObject.SetActive(false); // 적 비활성화
Debug.Log("적이 제거되었습니다!");
}
1. OnDisable과 OnDestroy의 차이점 OnDisable 오브젝트가 비활성화될 때 호출됩니다. 오브젝트는 여전히 메모리에 남아 있습니다(삭제되지 않음). 이후에 다시 활성화되면 **OnEnable()**이 호출됩니다. OnDestroy 오브젝트가 완전히 삭제될 때 호출됩니다. Destroy(gameObject)로 오브젝트가 제거되거나, 씬(Scene)이 변경될 때 실행됩니다. 삭제된 후에는 다시 활성화할 수 없습니다.
2. 언제 호출되나요? OnDisable() SetActive(false)로 오브젝트를 비활성화했을 때. 컴포넌트의 enabled를 false로 설정했을 때. 씬이 비활성화될 때도 호출됩니다. OnDestroy() Destroy(gameObject)로 오브젝트를 삭제했을 때. 씬이 변경되어 오브젝트가 완전히 사라질 때. 에디터에서 Play 모드가 종료될 때.
이렇게 하면
저렇게 스크립트를 비활성화 시키면 로그아웃이 됩니다. 저것을 실제로 저렇게 눌러서 비활성화 시키는 것 보다는 SetActive를 통해 비활성화 시키거나, 활성화 시킵니다.
이동
이제 게임 같은 코드를 작성 할 시간입니다. 여기서 이제 Input을 쓸 시간입니다. 파이썬에서 Input은 간단히 값을 넣을 수 있게 해주는 함수입니다. 예:
num = Input('숫자 입력:')
이렇게 하면 사용자가 값을 넣으면 그 값이 num에 들어가게 됩니다.
하지만 Unity에서는 다릅니다. Unity의 Input 클래스는 사용자의 입력(키보드, 마우스, 게임패드 등)을 감지하고 처리하는 데 사용됩니다. 게임 내에서 플레이어의 행동을 제어하거나 인터페이스와 상호작용할 때 핵심적으로 사용됩니다.
Input 클래스란? UnityEngine 네임스페이스에 포함된 클래스. 키보드, 마우스, 터치, 게임패드 입력을 읽고 처리할 수 있습니다. 게임 플레이에서 캐릭터 이동, 공격, 점프 등의 동작을 구현할 때 사용됩니다.
Input 클래스의 주요 메서드와 속성 키보드 입력 1. Input.GetKey(KeyCode key)
특정 키가 눌려있는 동안 호출됩니다.
if (Input.GetKey(KeyCode.W))
{
Debug.Log("W 키가 눌려 있습니다.");
}
2. Input.GetKeyDown(KeyCode key) 특정 키가 눌린 순간에만 호출됩니다.
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("스페이스바를 눌렀습니다.");
}
3. Input.GetKeyUp(KeyCode key) 특정 키가 떨어진 순간에 호출됩니다.
if (Input.GetKeyUp(KeyCode.Space))
{
Debug.Log("스페이스바를 뗐습니다.");
}
마우스 입력 1. Input.GetMouseButton(int button) 특정 마우스 버튼이 눌려있는 동안 호출됩니다. 버튼 번호: 0: 왼쪽 버튼 1: 오른쪽 버튼 2: 가운데 버튼
if (Input.GetMouseButton(0))
{
Debug.Log("마우스 왼쪽 버튼이 눌려 있습니다.");
}
2. Input.GetMouseButtonDown(int button) 특정 마우스 버튼이 눌린 순간에 호출됩니다.
if (Input.GetMouseButtonDown(1))
{
Debug.Log("마우스 오른쪽 버튼을 눌렀습니다.");
}
3. Input.GetMouseButtonUp(int button) 특정 마우스 버튼이 떨어진 순간에 호출됩니다.
if (Input.GetMouseButtonUp(0))
{
Debug.Log("마우스 왼쪽 버튼을 뗐습니다.");
}
2. Input.GetTouch(int index) 특정 터치 정보를 가져옵니다. 반환되는 터치 정보에는 터치 위치, 터치 상태 등이 포함됩니다.
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
Debug.Log($"첫 번째 터치 위치: {touch.position}");
}
기타 Input.anyKey 아무 키가 눌렸는지 확인합니다.
if (Input.anyKey)
{
Debug.Log("아무 키가 눌렸습니다.");
}
Input.anyKeyDown 아무 키가 눌린 순간을 감지합니다.
if (Input.anyKeyDown)
{
Debug.Log("아무 키가 눌렸습니다!");
}
Input.GetJoystickNames() 연결된 조이스틱 이름을 반환합니다.
string[] joystickNames = Input.GetJoystickNames();
foreach (string name in joystickNames)
{
Debug.Log($"연결된 조이스틱: {name}");
}
아 참고로, 저렇게 Input.anyKeyDown은 잘 생각해보면, 누르면 로직이 이루어져야 하기 때문에, 즉, True or False로 다뤄야하기 때문에 If로 로직을 짜야합니다.
왜 Update에?
자, 이런 Input을 왜 Update에 넣어야 할까요? 이것은 전에 설명했던 라이프 사이클과 관련이 깊습니다. 이제부터 이런 개념들은 자신이 하나하나 생각하면서 해야합니다. 먼저, Input 처리를 Update에 넣는 이유는 게임의 입력 감지가 프레임 단위로 일어나야 하기 때문입니다.
1. 입력과 Update의 연관성 Unity의 게임 루프 구조 Unity는 매 프레임마다 Update()를 호출합니다. 사용자의 입력(키보드, 마우스, 게임패드 등)은 매 순간 빠르게 변할 수 있으므로, 프레임 단위로 감지해야 합니다. Input.GetKey, Input.GetKeyDown 같은 입력 메서드도 매 프레임 호출될 때만 입력 상태를 확인할 수 있습니다.
2. Update에서 입력을 처리해야 하는 이유 (1) 입력은 실시간으로 변함 예: 키보드 버튼을 짧게 누르면 한 프레임만 눌렸다고 감지될 수 있습니다. 만약 입력 처리를 매 프레임마다 하지 않는다면, 사용자가 누른 입력을 놓칠 가능성이 높아집니다. Update()는 프레임마다 실행되므로, 실시간 입력을 감지하기 적합합니다.
(2) 게임 로직과 연계 대부분의 게임 동작(캐릭터 이동, 점프 등)은 사용자의 입력에 따라 실시간으로 반응해야 합니다. 예를 들어, W키를 누르면 캐릭터가 앞으로 움직여야 하죠. 이 동작은 매 프레임마다 실행되는 게임 로직과 연결되어야 합니다. 따라서, 입력 처리도 Update()에서 함께 이루어지는 것이 자연스럽습니다.
3. 왜 FixedUpdate나 LateUpdate가 아닌가? (1) FixedUpdate는 물리 연산 전용 FixedUpdate()는 일정한 간격으로 호출되므로 프레임 속도와 동기화되지 않습니다. 입력은 사용자의 실시간 반응이므로, 물리 연산보다 더 자주 확인해야 정확하게 처리할 수 있습니다. (2) LateUpdate는 모든 Update 이후 호출 LateUpdate()는 업데이트 후에 실행되므로, 입력 처리 후의 결과를 수정하거나 보완하는 용도로 사용됩니다. 입력 감지 자체는 Update()에서 처리하는 것이 더 직관적입니다.
일단 눈치채신 사람들도 있는데, Input에는 입력 함수는 3가지가 있습니다 down -> GetKeyDown stay -> GetKey up -> GetKeyUp 위에 예시에서 보던 것들이 있습니다. down은 눌렀을 때 True 반환하고 stay는 누르고 있을 때 True를 반환하며 up은 키를 누르고 키를 놓을 때 True를 반환합니다.
아 추가로 KeyCode에서 enter는 enter가 아니라 return으로 써야합니다. ESC는 ESC가 아니라 Escape입니다.
자, 여기서 질문. 만약에 이동한다고 치면은 GetKey를 써야하는데, 그렇다고 치면 이동하고 멈출 때는 GetKeyUp을 써야할까요, 아니면 어차피 키를 떼면은 False가 되어버리니 그대로 놨두는것이 맞을까요? 사실은 둘 다 가능합니다.
키를 떼면 GetKey는 자동으로 false가 되므로 GetKeyUp을 별도로 쓸 필요는 없습니다. 하지만 특정 상황에서는 GetKeyUp이 유용할 수 있습니다.
GetKey로 이동 구현 일반적으로 GetKey는 키가 눌려있는 동안 호출되므로 이동에 적합합니다. 키를 떼면 자동으로 입력이 멈추므로 별도로 GetKeyUp을 사용하지 않아도 됩니다.
void Update()
{
if (Input.GetKey(KeyCode.W))
{
Debug.Log("캐릭터가 앞으로 이동 중");
}
else
{
Debug.Log("캐릭터가 멈췄습니다");
}
}
GetKey(KeyCode.W)가 false로 돌아오면 캐릭터는 멈춥니다. 따라서 키를 뗀 상태를 별도로 처리할 필요가 없습니다.
GetKeyUp을 사용하는 경우 특정 이벤트를 트리거할 때 만약 키를 뗄 때 특별한 동작이 필요하다면, GetKeyUp을 사용합니다. 예를 들어: 캐릭터가 이동하다가 점프하거나 특별한 애니메이션을 재생. 키를 뗀 순간, 속도를 점진적으로 줄이거나 효과 적용.
void Update()
{
if (Input.GetKey(KeyCode.W))
{
Debug.Log("캐릭터가 앞으로 이동 중");
}
if (Input.GetKeyUp(KeyCode.W))
{
Debug.Log("캐릭터가 이동을 멈추며 속도를 줄입니다.");
}
}
GetKeyUp(KeyCode.W)는 키를 떼는 순간에만 호출되므로, 멈출 때 별도의 로직을 처리할 수 있습니다.
단순한 이동 구현이라면 GetKey만 사용하면 됩니다. 키를 떼면 자동으로 false가 되어 멈추기 때문입니다. 키를 뗄 때 특별한 동작(애니메이션, 감속 등)이 필요하다면 GetKeyUp을 추가적으로 활용하세요.
그런데 굳이 이렇게 할 필요가 있을까요? 사실 이러한 input을 간단하게 지정해줄 수 있는 키가 있습니다. Create에 Input Actions가 있습니다. 여기서 size, horizontal 등등....설정할 수 있습니다.
이렇게 되어있습니다. 이렇게 될 경우, 저희는 뭐 편하게 코드를 작성하면 됩니다. 여기는 Jump란 이름이 있기 때문에, 이렇게 될 경우, KeyCode와 space가 아닌 Jump라 적으면 됩니다.
if (Input.GetButton("Jump")) {
Debug.Log("준비");
}
if (Input.GetButtonDown("Jump")) {
Debug.Log("버튼 인식");
}
if (Input.GetButtonUp("Jump")) {
Debug.Log("버튼 out");
}
이렇게 말입니다. 더 편해졌죠? 근데 저 파일은 따로 오브젝트에 안 넣었는데도 공유가 됩니다 왜 그럴까요? Unity의 Input Actions는 전체 프로젝트에서 공통으로 사용할 수 있도록 설정된 입력 맵(input map) 시스템입니다. Input Actions는 하나의 공유되는 파일 또는 설정으로 관리됩니다. 이 파일에는 여러 입력 맵과 액션들이 정의되며, 게임의 여러 부분에서 이를 참조하고 사용할 수 있습니다. 예를 들어, "Jump"라는 액션을 정의하면, Input Actions 파일에 "Jump"와 연결된 키(Space 또는 Joystick Button)를 설정하고, 코드에서는 그냥 "Jump"라는 이름으로 이 액션을 호출하여 해당 입력을 처리할 수 있습니다.
결론적으로, Input Actions는 게임의 전역적인 입력 처리 시스템을 제공하는 설정 파일로, 프로젝트 전체에서 참조할 수 있는 공유 자원입니다. 이를 통해 코드에서 키 코드를 직접 사용하지 않고, 이름 기반으로 액션을 처리할 수 있습니다.
참고로 쓸 때에는 대소문자와 이름이 같아야 합니다.
GetAxis()
Input.GetAxis() 연속적인 값의 입력(예: 이동, 회전)을 처리하는 데 사용됩니다. Input Manager에서 정의된 가상 축의 값을 반환합니다. Input.GetAxis(string axisName): 지정된 축의 값을 반환합니다. Input.GetAxisRaw(string axisName): GetAxis와 유사하지만, 값의 스무딩(smoothing) 없이 즉각적인 값을 반환합니다. 기본적으로 "Horizontal"과 "Vertical" 축이 정의되어 있으며, 이는 키보드의 화살표 키나 W, A, S, D 키와 매핑되어 있습니다.
참고로 Axis는 축을 반환하게 때문에 if문을 안 쓰고, 값을 받을 변수를 지정합니다.
Input Manager
자, Unity 6에서는 추가로 Input Manager에 대해 알아야 합니다. Input Manager에서 사용하는 컨트롤 유형 Key (키) 물리적인 키보드의 W, Shift, Space Bar와 같은 키를 의미합니다.
Button (버튼) 물리적인 컨트롤러(예: 게임패드)의 X 버튼과 같은 버튼을 의미합니다.
가상 축 (Virtual Axis) 버튼이나 키와 같은 컨트롤에 매핑됩니다. 사용자가 컨트롤을 활성화하면, 축은 [–1..1] 범위의 값을 받게 됩니다. 이 값은 스크립트에서 사용할 수 있습니다.
그리고 문제는 지금 유니티 6에서는 이전 버전과 다릅니다. 위 설명은 이전 버전이지만 지금 버전에 대해 설명하겠습니다. 1. Input System이란? Unity의 새로운 Input System은 기존의 Input 클래스를 대체하기 위해 설계되었습니다. 기존의 방식이 정적 메서드를 사용해 입력을 처리했다면, 새로운 Input System은 객체 지향적이며 더 유연한 방식으로 다양한 입력 장치를 지원합니다.
주요 특징 다양한 입력 장치(키보드, 마우스, 게임패드, 터치스크린 등)를 통합적으로 관리. 액션 기반 입력 처리 방식으로 더 구조적이고 직관적. 키 재설정(Runtime Rebinding)과 복잡한 입력 조합 처리 지원.
2. Input System 설치하기 2.1 패키지 매니저로 Input System 설치 Unity 에디터에서 Window > Package Manager를 엽니다. Unity Registry 탭을 선택합니다. 검색창에 Input System을 입력하고 선택한 뒤 Install 버튼을 클릭합니다. 2.2 설치 후 입력 시스템 변경 Input System 설치 후 Unity가 "새로운 Input System으로 전환하시겠습니까?"라는 메시지를 표시합니다.
Yes를 선택하세요. → 이 작업은 기존의 Input 클래스 대신 새로운 Input System을 사용할 수 있도록 설정합니다. → Unity가 재시작됩니다.
3. Input Action Asset 생성 3.1 Input Action Asset이란? Input Action Asset은 입력 이벤트와 장치 간의 매핑을 설정하는 데이터 파일입니다. 입력을 관리하고 처리할 수 있도록 구조화된 방법을 제공합니다.
3.2 Input Action Asset 생성 단계 Project 창에서 마우스 오른쪽 버튼을 클릭하고 Create > Input Actions를 선택합니다. 파일 이름은 PlayerInput 등 직관적으로 지정합니다. 생성된 .inputactions 파일을 더블 클릭하여 Input Action Editor를 엽니다.
4. Input Action Asset 설정 4.1 Action Map 생성 Action Map은 입력을 그룹으로 묶는 단위입니다. 예: "Player"는 플레이어의 이동, 점프 등을 관리하는 입력 그룹. Action Maps 영역에서 + 버튼을 클릭하여 "Player"라는 Action Map을 생성합니다. 4.2 Action 생성 Action은 개별 동작(예: "Move", "Jump")을 정의합니다. "Player" Action Map 아래 Actions 영역에서 + 버튼을 클릭합니다. 이름을 Move, Jump 등으로 지정합니다. 4.3 Binding 생성 Binding은 입력 장치(키보드, 게임패드 등)와 Action을 연결합니다. Move Action을 선택한 뒤, 오른쪽 Bindings 영역에서 + 버튼을 클릭합니다. Vector2 타입으로 설정하여 방향 입력을 처리합니다. 키보드: WASD 또는 화살표 키를 바인딩합니다. 게임패드: Left Stick을 추가 바인딩으로 설정합니다. Jump Action을 선택한 뒤 + 버튼을 클릭합니다. 키보드의 Space 키를 바인딩합니다.
자 그런데 binding에는 add binding add Positive\Negative modifier add binding with one modifier add binding with two modifiers 이렇게 네가지 옵션이 있습니다 각각 어떤것을 의미하는지 알아보겠습니다.
1. Add Binding 의미: 단순히 새 바인딩을 추가합니다. 입력 장치(키보드, 마우스, 게임패드 등)에서 특정 입력을 액션에 연결합니다. 사용 사례: 하나의 액션에 여러 입력(예: "Jump"는 스페이스바와 게임패드의 A 버튼)을 연결할 때 사용합니다.
2. Add Positive/Negative Modifier 의미: 이 옵션은 Axis(축) 입력에 **양(Positive)**과 음(Negative) 방향을 추가하는 기능을 제공합니다. 예를 들어, Horizontal 액션에서 **왼쪽(-1)**과 **오른쪽(+1)**을 정의할 때 유용합니다.
구조: Positive: 축의 양(Positive) 방향을 담당하는 키나 입력 장치. Negative: 축의 음(Negative) 방향을 담당하는 키나 입력 장치. 사용 사례: 키보드의 A와 D 키를 Horizontal 축의 Negative/Positive로 설정하거나, 게임패드의 Left Stick 좌우 움직임을 연결할 때 사용합니다.
예제: Action: Move Binding: Add Positive/Negative Modifier Positive: D 키 (오른쪽 이동) Negative: A 키 (왼쪽 이동)
3. Add Binding with One Modifier 의미: 특정 **Modifier Key(수정 키)**를 누른 상태에서만 입력이 활성화되도록 바인딩을 추가합니다. Modifier Key란 Shift, Ctrl, Alt 같은 키를 말합니다.
구조: Modifier Key: 입력을 활성화하려면 반드시 누르고 있어야 하는 키. Binding: Modifier Key가 눌린 상태에서 동작할 입력 키나 버튼. 사용 사례:
Shift + A를 특정 액션(예: 대쉬)에 바인딩. Ctrl + W를 다른 동작(예: 문 열기)에 바인딩.
예제: Action: Dash Binding: Add Binding with One Modifier Modifier Key: Shift Key: W
4. Add Binding with Two Modifiers 의미: 두 개의 Modifier Key를 조합하여 입력을 활성화하도록 설정합니다. 예를 들어, Ctrl + Alt + S 같은 조합을 처리할 수 있습니다.
구조: Modifier Key 1: 첫 번째 수정 키. Modifier Key 2: 두 번째 수정 키. Binding: Modifier Keys가 모두 눌린 상태에서 동작할 입력 키나 버튼.
사용 사례: Ctrl + Shift + E를 특정 액션에 바인딩. 고급 입력 조합(예: 편집 도구에서 단축키 조합)을 처리할 때 사용.
예제: Action: SpecialAction Binding: Add Binding with Two Modifiers Modifier Key 1: Ctrl Modifier Key 2: Shift Key: E
액션 편집기 열기 입력 액션 편집기는 액션 자산을 더블 클릭하여 열면 표시됩니다. 또한 프로젝트 설정 창에서 Edit > Project Settings > Input System Package로 이동하여 액션 자산이 프로젝트 전역 액션으로 할당된 경우에도 열 수 있습니다. 액션 편집기 패널 입력 액션 편집기는 세 개의 패널로 나누어져 있습니다. (A, B, C로 표시됨) 액션 맵 구성 액션 맵 추가: 액션 맵 패널의 헤더에서 + 아이콘을 클릭하여 새 액션 맵을 추가합니다. 액션 맵 이름 변경: 이름을 길게 클릭하거나, 액션 맵을 마우스 오른쪽 버튼으로 클릭한 후 이름 변경을 선택합니다. 액션 맵 이름에는 슬래시(/)를 포함할 수 없습니다. 액션 맵 삭제: 액션 맵을 마우스 오른쪽 버튼으로 클릭하고 삭제를 선택합니다. 액션 맵 복제: 액션 맵을 마우스 오른쪽 버튼으로 클릭하고 복제를 선택합니다.
액션 구성 액션 추가: 액션 열의 헤더에서 + 아이콘을 클릭하여 새 액션을 추가합니다. 액션 이름 변경: 이름을 길게 클릭하거나, 액션을 마우스 오른쪽 버튼으로 클릭한 후 이름 변경을 선택합니다. 액션 삭제: 액션을 마우스 오른쪽 버튼으로 클릭하고 삭제를 선택합니다. 액션 복제: 액션을 마우스 오른쪽 버튼으로 클릭하고 복제를 선택합니다.
액션 타입 및 제어 타입 액션을 선택하면 오른쪽 창에서 해당 액션의 속성을 편집할 수 있습니다. 액션 속성 액션 타입 액션 타입 설정을 통해 Button, Value, 또는 PassThrough를 선택할 수 있습니다. Button: 키보드 키, 마우스 클릭 또는 게임패드 버튼과 같이 단순히 켜고 끄는 온/오프 스타일의 상호작용을 나타냅니다. Value: 마우스 이동, 조이스틱, 게임패드 스틱, 또는 장치 방향과 같이 시간이 지남에 따라 계속 변화하는 값을 나타냅니다. PassThrough: 기본적으로 값 유형이지만, Value와 다른 점은 장치 제어에서 수신되는 값에 대한 기본적인 정보만 제공합니다. 제어 타입 제어 타입 설정을 통해 액션에서 예상하는 제어 유형을 선택할 수 있습니다. 이는 UI에서 바인딩을 설정할 때 표시되는 제어를 제한하며, 제어를 상호작용적으로 바인딩할 수 있는 장치도 제한합니다.
바인딩 바인딩 추가: 원하는 액션에 바인딩을 추가하려면 + 아이콘을 클릭하고 메뉴에서 바인딩 유형을 선택합니다. 바인딩 삭제: 바인딩을 마우스 오른쪽 버튼으로 클릭하고 삭제를 선택합니다. 바인딩 복제: 바인딩을 마우스 오른쪽 버튼으로 클릭하고 복제를 선택합니다. 바인딩은 여러 개를 추가할 수 있습니다. 이는 다양한 입력 장치에서 입력을 처리할 때 유용합니다. 예를 들어, 기본적으로 "Move" 액션에는 왼쪽 게임패드 스틱과 WASD 키에 대한 바인딩이 포함되어 있습니다. 바인딩 속성 제어 선택 바인딩의 가장 중요한 속성은 바인딩된 제어 경로입니다. 이를 편집하려면 Path 드롭다운을 열어 Control picker 창을 통해 선택할 수 있습니다. Control Picker 창에서 입력 장치와 제어를 탐색하고 바인딩할 수 있습니다. 제어 타입에 따라 사용할 수 있는 제어 목록이 필터링됩니다. 예를 들어, 제어 타입이 Vector2일 경우 2D 벡터 값을 생성할 수 있는 제어만 선택할 수 있습니다.
컴포지트 바인딩 편집 컴포지트 바인딩은 여러 부분으로 구성된 바인딩입니다. 예를 들어, 2D 벡터 컴포지트는 네 개의 버튼(W, A, S, D)을 사용하여 2D 스틱 입력을 시뮬레이션합니다.
2D 벡터 컴포지트 추가 액션에 컴포지트 바인딩을 추가하려면, + 아이콘을 클릭하고 컴포지트 바인딩 유형을 선택합니다.
컴포지트 바인딩 속성 컴포지트 바인딩에는 개별적인 부분에 대한 바인딩이 포함됩니다. 각 부분을 편집하여 하나의 제어처럼 작동하도록 할 수 있습니다. 제어 체계 편집 입력 액션 자산은 여러 개의 제어 체계를 가질 수 있습니다. 제어 체계는 다양한 장치 유형에 대해 다른 바인딩 세트를 활성화하거나 비활성화하는 방법을 정의합니다.
제어 체계 편집: 제어 체계 드롭다운 메뉴에서 제어 체계를 추가하거나 선택하여 해당 체계에 맞는 바인딩을 편집할 수 있습니다.
아니면, 먼저 이렇게 action type을 Value, Control Type을 Vector 2로 설정하고 그 Actions에 있는 +을 누르면
원래 Positive 혹은 Negative가 Up Down Left Right으로 바뀝니다. 이제 이것을 누르고 WASD로 이름 바꾸고 뭐시기 뭐시기....이제 한번 해봅시다.
사실 이전 버전처럼 쓸려면 새로운 Input System API를 사용해야 합니다. 따라서 기존처럼 이름 기반으로 Input.GetButton("Up")을 호출하는 방식은 새로운 Input System에서는 지원하지 않습니다.
Unity Input System 1.11.2에서는 InputAction을 전역적으로 사용할 수 있습니다. 특히, InputActionAsset을 미리 프로젝트 전역으로 설정했다면 이름 기반으로 바로 접근 가능합니다.
먼저 아까 말했듯이 전역 이름 기반으로 작동하는 법에 대해 알아보겠습니다. 전역 이름 기반으로 작동하려면? 프로젝트 전역 설정 Input Actions Asset 생성 및 구성 Project 창에서 Input Actions Asset 파일(예: PlayerControls.inputactions)을 생성합니다. Action Map과 Action 이름을 설정합니다(예: Move, Jump).
Default Input Actions Asset 설정 Edit > Project Settings > Input System Package로 이동. Default Input Actions Asset에 PlayerControls.inputactions 파일을 드래그하여 설정합니다.
정확한 Action 이름 사용 InputSystem.FindAction()은 이름에 의존하므로 Action Map 및 Action 이름이 정확히 일치해야 합니다.
주의사항 이름 충돌 방지: 여러 Action Map에 동일한 이름의 Action이 있으면 문제가 발생할 수 있습니다. 성능 고려: InputSystem.FindAction()은 런타임에서 액션을 검색하므로, 반복 호출보다는 한 번 가져온 후 캐싱하는 것이 좋습니다.
InputSystem.FindAction()을 사용하는 방식
예시
using UnityEngine;
using UnityEngine.InputSystem; // Input System 기능 사용
public class GlobalInputExample : MonoBehaviour
{
private void Update()
{
// "Move"라는 이름의 액션 가져오기
var moveAction = InputSystem.FindAction("Move", true);
// 액션이 존재하는지 확인
if (moveAction != null)
{
// Move 액션에서 Vector2 값을 읽어오기 (WASD/화살표 입력)
Vector2 movement = moveAction.ReadValue<Vector2>();
Debug.Log($"Movement Input: {movement}");
}
else
{
Debug.LogWarning("Move 액션을 찾을 수 없습니다. 설정을 확인하세요.");
}
}
}
1. InputSystem 네임스페이스 사용
using UnityEngine.InputSystem;
새로운 Input System 기능을 사용하기 위해 필요한 네임스페이스입니다. Unity의 기본 Input 클래스를 대체하며, Input Actions 및 장치 제어를 제공합니다.
2. InputSystem.FindAction() 함수
var moveAction = InputSystem.FindAction("Move", true);
InputSystem.FindAction(string name, bool throwIfNotFound) 여기서 InputSystem은 Unity Engine의 Input System 패키지에서 제공하는 클래스입니다. Unity의 새로운 Input System에서는 InputSystem이라는 클래스가 전역적으로 Input System과 관련된 여러 기능을 제공하는 유틸리티 클래스로 존재합니다. InputSystem의 역할 InputSystem은 다음과 같은 역할을 합니다:
장치와 액션 관리 연결된 입력 장치 정보를 가져오거나, 장치를 관리할 수 있습니다. Input Action을 검색하거나 제어할 수 있습니다.
Input System 초기화 및 설정 Input System의 동작을 초기화하거나 리셋할 때 사용할 수 있습니다.
이벤트 및 콜백 관리 입력 이벤트를 수동으로 처리하거나, 특정 상황에서만 입력을 수신할 수 있도록 제어합니다. name: 찾고자 하는 액션의 이름입니다. 이 이름은 Input Actions Asset에 정의한 Action 이름과 정확히 일치해야 합니다. 예: "Move", "Jump", "Attack" 등 throwIfNotFound: 액션을 찾을 수 없을 때 예외를 던질지 여부. true: 액션이 없으면 예외를 던짐. false: 단순히 null을 반환.
반환값: InputAction: 성공적으로 찾은 경우 반환. null: 액션을 찾지 못한 경우 반환(또는 예외).
3. Null 검사
if (moveAction != null)
{
// Move 액션에서 값 읽기
}
else
{
Debug.LogWarning("Move 액션을 찾을 수 없습니다.");
}
moveAction이 null인지 확인하여 에러를 방지합니다. 액션이 없을 경우 Debug.LogWarning으로 경고 메시지를 출력합니다.
4. ReadValue<T>() 함수
Vector2 movement = moveAction.ReadValue<Vector2>();
ReadValue<T>(): 입력된 값을 가져오는 함수. T: 값의 타입 (예: Vector2, float 등). Move 액션은 보통 2D 움직임을 다루므로, Vector2 타입을 사용합니다. 예: (1, 0)은 오른쪽, (-1, 0)은 왼쪽.
Debug.Log() 함수
Debug.Log($"Movement Input: {movement}");
입력값을 Unity 콘솔에 출력하여 디버깅할 수 있습니다. $"텍스트 {변수}"는 문자열과 변수의 값을 결합하는 문자열 보간 방식입니다.
그런데 이렇게 보면 질문이 많이 나올 수 있습니다. 먼저 저 Move라는 것이 여러 파일에 있다면 어떻게 될까요 InputSystem.FindAction("Move", true)에서 파일 충돌 가능성 InputSystem.FindAction("Move", true)은 프로젝트 내의 모든 Input Action Asset에서 "Move"라는 이름의 액션을 검색합니다.
동일한 이름의 액션이 여러 파일에 있을 경우: Unity는 검색할 때 가장 먼저 발견된 액션을 반환합니다. 여러 Input Action Asset이 있고 동일한 이름의 Action이 있을 경우 만약 프로젝트에 다음과 같이 여러 Input Action Asset이 존재한다고 가정합니다: Input_control(1): "Move" 액션 포함 Input_control(2): "Move" 액션 포함 Input_control(3): "Move" 액션 포함
이 경우, InputSystem.FindAction("Move", true)는 프로젝트 전체를 검색합니다.
발생할 수 있는 문제: 동일한 이름의 액션("Move")이 여러 Asset에 존재하면, FindAction은 가장 먼저 발견된 액션을 반환합니다. 어떤 Asset의 "Move" 액션이 반환될지는 불확실하며, 의도치 않은 동작이 발생할 가능성이 있습니다.
해결 방법: 특정 Asset에서만 액션을 검색하려면 해당 Asset을 명시적으로 로드해야 합니다.
var asset = Resources.Load<InputActionAsset>("Input_control(1)"); // 특정 Asset 로드
var moveAction = asset.FindAction("Move", true); // 이 Asset 내에서만 "Move" 검색
Action Map까지 명시적으로 지정하면 더욱 안전합니다.
var asset = Resources.Load<InputActionAsset>("Input_control(1)");
var moveAction = asset.FindActionMap("PlayerControls").FindAction("Move", true);
그런데 저 InputActionAsset은 뭐고 InputSystem은 뭘까요 코드를 보면서 이해해보겠습니다 var asset = Resources.Load<InputActionAsset>("Input_control(1)"); var: var는 변수 선언 시 타입을 명시하지 않고 컴파일러가 변수의 타입을 자동으로 추론하도록 하는 키워드입니다. 예를 들어, var x = 10;이라면 컴파일러는 x를 int 타입으로 추론합니다. 이 코드에서 asset은 InputActionAsset 타입의 변수로 추론됩니다.
Resources: Resources는 Unity에서 제공하는 클래스입니다. Resources 폴더 내의 리소스 파일들을 로드할 수 있는 기능을 제공합니다. Resources.Load() 메서드는 Resources 폴더에 있는 특정 리소스를 불러오는 데 사용됩니다.
Load: Load<T>() 메서드는 Resources 폴더 내에서 지정된 경로와 이름에 해당하는 리소스를 찾아서 반환합니다. 이 메서드는 제네릭 메서드로, <InputActionAsset>와 같이 타입을 명시하는데, 이는 로드하려는 리소스의 타입을 지정합니다. 예를 들어, "Input_control(1)" 파일이 InputActionAsset 타입이라면 InputActionAsset 타입으로 반환됩니다.
<InputActionAsset>: 이 부분은 제네릭 타입 매개변수를 설정하는 부분입니다. Resources.Load 메서드는 불러오는 리소스의 타입을 명시할 수 있는데, 여기서는 InputActionAsset 타입을 지정하고 있습니다. InputActionAsset은 Unity Input System에서 사용하는 액션 매핑을 저장하는 파일 형식입니다.
"Input_control(1)": Load 메서드에 전달되는 문자열은 Resources 폴더 내의 파일 경로 및 이름을 나타냅니다. "Input_control(1)"은 Resources 폴더 안에 있는 Input_control(1)이라는 이름의 InputActionAsset을 불러오겠다는 뜻입니다. 경로를 Resources/ 폴더 내에 상대적으로 지정하고, 파일 확장자는 .asset으로 추정됩니다.
2. var moveAction = asset.FindAction("Move", true); asset: 앞서 로드한 InputActionAsset 타입의 변수입니다. asset은 InputActionAsset 객체로, 입력 시스템 관련 액션 데이터를 저장하고 있는 객체입니다.
FindAction: FindAction 메서드는 InputActionAsset에서 특정 이름의 액션을 찾는 기능을 합니다. 여기서 "Move"라는 이름의 액션을 찾고 있습니다. 이 메서드는 두 번째 매개변수로 true를 받습니다. true는 액션이 없을 경우, 해당 액션을 새로 생성할지 여부를 나타냅니다. 여기서 true를 전달하면 액션이 없을 경우 자동으로 새로 생성됩니다.
"Move": "Move"는 찾고자 하는 액션의 이름입니다. 이는 InputActionAsset에 정의된 특정 액션 이름과 일치해야 합니다. 이 예시에서는 "Move"라는 이름의 액션을 찾고 있습니다.
요약: var asset = Resources.Load<InputActionAsset>("Input_control(1)"); Resources.Load<InputActionAsset>("Input_control(1)"): Resources 폴더에서 Input_control(1)이라는 이름의 InputActionAsset을 불러옵니다. var asset: 이 결과를 asset 변수에 할당하며, asset은 InputActionAsset 타입이 됩니다.
var moveAction = asset.FindAction("Move", true); asset.FindAction("Move", true): asset 객체에서 "Move"라는 이름의 액션을 찾습니다. 없으면 새로 생성합니다. var moveAction: 찾은 액션을 moveAction 변수에 할당합니다.
차이점?
var moveAction = InputSystem.FindAction("Move", true);
var asset = Resources.Load<InputActionAsset>("Input_control(1)");
var moveAction = asset.FindAction("Move", true);
이 두개의 차이점을 보겠습니다. 1. var moveAction = InputSystem.FindAction("Move", true); 이 방법은 Input System의 전역적인 액션 관리 시스템에서 "Move"라는 이름을 가진 액션을 찾는 방법입니다. InputSystem.FindAction 메서드는 전역적으로 등록된 Input Actions에서 액션을 찾습니다. 액션 이름을 기준으로 찾기 때문에, 이 방식은 특정 액션이 어디에서 정의되었는지에 관계없이 시스템 전체에서 해당 액션을 찾아 반환합니다. 첫 번째 인자는 찾고자 하는 액션의 이름인 "Move"입니다. 두 번째 인자인 true는 액션이 존재하지 않을 경우 예외를 던지도록 설정하는 옵션입니다. 기본적으로는 false로 설정되어 있으며, 이 경우 액션을 찾지 못하면 null을 반환합니다. true를 설정하면, 액션이 없을 경우 예외가 발생하여 코드 흐름을 중단합니다. 장점: 특정 액션을 쉽게 찾을 수 있으며, 코드가 간결합니다. 이 방식은 액션이 코드에 전역적으로 등록되어 있을 때 유용합니다. 단점: 액션이 특정 InputActionAsset에 속해 있는 경우, 그 액션을 찾기 어려울 수 있습니다. 예를 들어, 여러 액션이 포함된 InputActionAsset이 여러 개 있을 때는 정확히 어떤 Asset에서 액션을 찾았는지 추적하기 어려울 수 있습니다.
2. var asset = Resources.Load<InputActionAsset>("Input_control(1)"); var moveAction = asset.FindAction("Move", true); 이 방법은 특정 Input Action Asset에서 "Move"라는 액션을 찾는 방식입니다.
Resources.Load<InputActionAsset>("Input_control(1)"): 이 코드는 Resources 폴더에서 InputActionAsset을 로드합니다. 이때 "Input_control(1)"은 로드하려는 파일의 경로입니다. 즉, InputActionAsset은 Unity에서 정의한 입력 설정 파일(예: InputActionAsset이 포함된 .inputactions 파일)을 나타냅니다.
asset.FindAction("Move", true): 로드된 InputActionAsset 객체에서 "Move"라는 이름을 가진 액션을 찾습니다. FindAction 메서드는 해당 InputActionAsset 내에서만 "Move" 액션을 찾고, 두 번째 인자인 true는 액션이 없을 경우 예외를 발생시키도록 설정합니다.
장점: 이 방법은 특정 입력 자산(Asset) 내에서 액션을 찾을 수 있기 때문에, 여러 Input Action Asset이 존재할 경우 각 Asset에서 정의된 액션을 명확하게 찾을 수 있습니다. 리소스 폴더에서 액션을 로드하는 방식은 유연성과 정확도를 제공합니다.
단점: 이 방식은 코드에서 해당 InputActionAsset을 명시적으로 로드하고 사용하는 방식이기 때문에, 리소스를 로드하는 과정에서 일부 성능 오버헤드가 발생할 수 있습니다. 또한, 리소스를 로드하는 경로가 정확해야 합니다.
두 코드의 차이점 요약: 전역 액션 검색 vs 특정 Asset 내 액션 검색: 첫 번째 방법 (InputSystem.FindAction)은 전역적으로 등록된 액션을 찾습니다. 이 방법은 여러 액션이 등록된 상황에서 빠르게 액션을 찾을 수 있지만, 액션이 어느 Asset에 속하는지 명시적으로 알 수 없습니다. 두 번째 방법은 특정 InputActionAsset에서 액션을 찾습니다. 여러 입력 자산 중에서 특정 Asset에 포함된 액션을 찾을 수 있으며, 액션의 관리와 추적이 용이합니다.
Resources.Load 사용 여부: 두 번째 방법은 리소스에서 액션을 로드해야 하므로, 리소스 파일이 미리 Resources 폴더에 있어야 하고, 해당 경로로 로드가 되어야 합니다. 이는 더 많은 제어가 가능하지만, 리소스를 관리하는 데 있어서 추가적인 주의가 필요합니다. 에러 처리: 두 코드 모두 true를 사용해 액션이 없으면 예외를 발생시키도록 설정되어 있습니다. 따라서 액션이 존재하지 않는 경우, 예외를 통해 코드 흐름을 제어할 수 있습니다.
InputSystem? InputActionAsset? InputSystem과 InputActionAsset의 차이점 InputSystem: InputSystem은 클래스입니다. Unity의 새로운 입력 시스템을 관리하는 핵심 클래스이며, InputSystem 클래스는 전역적으로 입력 액션을 처리하고, 다양한 입력 장치와의 상호작용을 관리합니다. 주로 전역적인 입력 처리와 입력 액션을 정의하고, 액션을 찾아서 실행하는 등의 기능을 담당합니다. 예를 들어 InputSystem.FindAction() 메서드는 InputSystem 클래스에서 제공되는 메서드입니다. InputSystem 클래스는 여러 입력 장치의 상태를 추적하고, 이를 통해 게임의 다양한 입력 처리(예: 키보드, 마우스, 게임패드 등)를 할 수 있습니다.
InputActionAsset: InputActionAsset은 클래스이지만, 액션을 정의하는 컨테이너로 좀 더 특화된 타입입니다. 이는 Unity의 Input System에서 입력을 처리하는 설정 파일을 나타내는 클래스입니다. InputActionAsset은 여러 개의 InputAction 객체를 포함할 수 있는 컨테이너 역할을 합니다. 즉, 여러 액션을 한 파일 내에서 관리할 수 있게 해주는 구조입니다. 입력 액션 정의와 관련된 데이터 구조로, 이 파일 내에 액션, 바인딩, 상호작용 및 조건 등을 설정할 수 있습니다. 예를 들어 "Move" 액션이 포함된 InputActionAsset은 특정 키나 조작에 대한 입력을 정의합니다. InputActionAsset은 자원(asset)으로서, Unity 프로젝트 내에서 .inputactions 파일 형태로 정의되고, Unity 에디터에서 이 파일을 관리할 수 있습니다. 이 파일을 코드에서 Resources.Load<InputActionAsset>() 또는 AssetDatabase.LoadAssetAtPath<InputActionAsset>() 등을 사용해 로드하여 사용할 수 있습니다.
InputActionAsset은 클래스인가, 타입인가? InputActionAsset은 클래스입니다. 사실 타입이라고 말하는 것도 맞지만, 더 구체적으로 말하자면 InputActionAsset은 Unity의 클래스 중 하나입니다. 이는 Unity 엔진에서 특정 기능을 가진 객체를 정의하는 클래스이며, 그 타입은 InputActionAsset입니다.
클래스(Class)와 타입(Type)은 개념적으로 비슷하지만, 정확히 말하면 타입은 객체의 형식을 지정하는 개념이고, 클래스는 그 객체를 생성할 수 있는 설계도입니다. 따라서 InputActionAsset은 클래스이자, 해당 클래스의 인스턴스를 만드는 타입이기도 합니다.
타입의 의미 InputActionAsset이 클래스인 동시에 타입으로 언급되는 이유는, Unity의 InputActionAsset을 객체로 사용할 수 있기 때문입니다. 즉, InputActionAsset 타입은 InputActionAsset 클래스의 인스턴스를 의미합니다.
참고로 Move는 Action의 이름입니다. 좀 더 구체적으로 설명하면: Action Map: Action Map은 여러 개의 InputAction을 그룹화하는 컨테이너 역할을 합니다. 보통 하나의 게임에서 여러 가지 입력 방식이 필요하므로, 여러 개의 액션을 논리적으로 그룹화하고 관리할 수 있도록 합니다. 예를 들어, "PlayerControls"라는 Action Map에는 "Move", "Jump", "Attack"과 같은 여러 개의 Action들이 포함될 수 있습니다. Action:
Action은 실제로 입력에 대한 구체적인 동작을 정의합니다. 예를 들어, "Move"라는 이름의 Action은 캐릭터를 이동시키는 입력을 담당합니다. InputAction 객체는 이러한 단일 입력 행동을 정의하며, 이 액션은 키보드, 마우스, 게임패드 등 다양한 입력 장치에 대응할 수 있습니다. 따라서, "Move"는 Action의 이름이고, 이 Action은 특정 Action Map에 속할 수 있습니다. 예를 들어, "PlayerControls"라는 Action Map에 "Move"라는 Action이 있을 수 있는 형태입니다.