Skip to content

Stellar-F0X/Unity-Input-Layer

Repository files navigation

Unity Input Layer System

Unity의 Input System을 레이어 기반으로 관리할 수 있는 확장 시스템입니다.
스택 구조를 통해 UI, 게임플레이, 메뉴 등 다양한 컨텍스트에서 입력 우선순위를 자동으로 관리합니다.

주요 기능

  • 스택 기반 입력 관리: 레이어를 스택에 푸시/팝하여 입력 컨텍스트를 자동 전환
  • 우선순위 자동 처리: 최상단 레이어만 입력을 받아 충돌 방지
  • 중앙화된 제어: InputManager를 통한 전역 입력 흐름 관리
  • 컴포넌트 기반: InputReceiver로 입력 로직을 컴포넌트화

요구사항

  • Unity 2019.1 이상
  • Unity Input System 패키지

설치

Package Manager를 통한 설치

  1. Unity 에디터에서 Window > Package Manager 열기
  2. + 버튼 클릭 → Add package from git URL... 선택
  3. 다음 URL 입력:
https://github.com/Stellar-F0X/Unity-Input-Layer.git

manifest.json을 통한 설치

Packages/manifest.json 파일에 다음 줄을 추가:

{
  "dependencies": {
    "com.stellarfox.input-layer": "https://github.com/Stellar-F0X/Unity-Input-Layer.git"
  }
}

빠른 시작

1. Input Action Asset 설정

Project Settings > Input System Package에서 Input-wide로 Input Action Asset을 설정합니다.

2. InputManager 설정

씬에 InputManager가 자동으로 생성되거나, 직접 GameObject에 추가합니다.

추가된 InputManager 컴포넌트의 Inspector에서 Root로 삼을 레이어를 설정합니다.

[SerializeField] private InputLayerName _rootLayer; // "Player" 등

주의 Root 레이어는 런타임 중에 없앨 수 없습니다.

3. 기본 사용법

using InputLayer.Runtime;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    [SerializeField] private InputLayerController controller;

    private void Start()
    {
        controller.PushInputLayer("UI"); // UI 레이어 추가
    }

    private void OnMenuClosed()
    {
        controller.PopInputLayer(); // UI 레이어 제거 (아래 있는 레이어로 자동 복귀)
    }
}

핵심 컴포넌트

InputLayerController

레이어 스택을 조작하고 이벤트를 구독할 수 있는 컴포넌트입니다. GameObject에 추가하여 사용합니다.

메서드

[SerializeField] private InputLayerController controller;

// 레이어 푸시
controller.PushInputLayer("UI");

// 레이어 팝
controller.PopInputLayer();

// 루트 제외 모든 레이어 제거
controller.PopAllInputLayersExpectRoot();

// 현재 최상단 레이어 확인
InputLayer currentLayer = controller.peekInputLayer;

이벤트

public class SomeClass : MonoBehaviour
{
    [SerializeField] private InputLayerController controller;

    private void Start()
    {
        controller.onPushedInputLayer += OnLayerPushed;
        controller.onPoppedInputLayer += OnLayerPopped;
    }

    private void OnLayerPushed(InputLayer layer)
    {
        Debug.Log($"레이어 추가됨: {layer.mapName}");
    }

    private void OnLayerPopped(InputLayer layer)
    {
        Debug.Log($"레이어 제거됨: {layer.mapName}");
    }

    private void OnDestroy()
    {
        controller.onPushedInputLayer -= OnLayerPushed;
        controller.onPoppedInputLayer -= OnLayerPopped;
    }
}

InputReceiver

특정 레이어의 입력을 받는 컴포넌트입니다. GameObject에 추가하고 Inspector에서 레이어를 지정합니다.

설정

public class PlayerController : MonoBehaviour
{
    [SerializeField] private InputReceiver inputReceiver; // Inspector에서 레이어 지정 필요
}

입력 읽기 메서드

private void Update()
{
    // 버튼이 이번 프레임에 눌렸는지
    if (inputReceiver.ReadButtonDown("Jump"))
    {
        Jump();
    }

    // 버튼이 현재 눌려있는지
    if (inputReceiver.ReadButton("Fire"))
    {
        Shoot();
    }

    // 버튼이 이번 프레임에 떼어졌는지
    if (inputReceiver.ReadButtonUp("Aim"))
    {
        StopAiming();
    }

    // 값 읽기 (Vector2, float 등)
    if (inputReceiver.ReadInput("Move", out Vector2 movement))
    {
        Move(movement);
    }
}

콜백 등록

private void Start()
{
    // 콜백 등록 - 레이어가 활성화되지 않아도 콜백은 동작합니다
    _inputReceiver.RegisterInputAction("Jump", InputCallback.Performed, OnJumpPerformed);
}

private void OnJumpPerformed(InputAction.CallbackContext context)
{
    Debug.Log("Jump performed!");
}

private void OnDestroy()
{
    // 콜백 제거 필수
    _inputReceiver.UnregisterInputAction("Jump", InputCallback.Performed);
}

주의사항

  • ReadInput, ReadButton, ReadButtonDown, ReadButtonUp은 해당 InputReceiver의 레이어가 최상단 레이어가 아니면 항상 false를 반환합니다
  • 콜백(RegisterInputAction)은 레이어 활성화 여부와 무관하게 동작합니다
  • InputReceiver는 지정된 레이어의 Input Action에만 접근 가능합니다

InputLayerName

인스펙터에서 Input Action Map을 선택할 수 있는 직렬화 가능한 타입입니다.

[SerializeField] 
private InputLayerName _playerLayer;

private void Start()
{
    Debug.Log(_playerLayer.name); // "Player"
    Debug.Log(_playerLayer.id);   // Guid
}

InputCallback

입력 콜백 타입을 지정하는 플래그 열거형입니다.

// 단일 콜백
InputCallback.Started
InputCallback.Canceled
InputCallback.Performed

// 복합 콜백
InputCallback.All // Started | Canceled | Performed
InputCallback.Started | InputCallback.Performed

사용 예시

UI 메뉴 시스템

public class PauseMenu : MonoBehaviour
{
    public InputLayerController controller;
    
    private void OnEnable()
    {
        controller.PushInputLayer("UI"); // 메뉴가 열리면 UI 레이어 활성화
    }

    private void OnDisable()
    {   
        controller.PopInputLayer(); // 메뉴가 닫히면 이전 레이어로 복귀
    }
}

대화 시스템

public class DialogueSystem : MonoBehaviour
{
    public InputReceiver dialogueInput;
    public InputLayerController controller;

    private void StartDialogue()
    {
        controller.PushInputLayer("Dialogue"); // 대화 시작시, Dialogue 레이어만 활성화
        
        dialogueInput.RegisterInputAction("Submit", InputCallback.Performed, OnDialogueAdvance);
    }

    private void EndDialogue()
    {
        dialogueInput.UnregisterInputAction("Submit", InputCallback.Performed);
        
        controller.PopInputLayer(); // 대화 종료시, Dialogue 레이어를 제거하고 기존 레이어 활성화.
    }

    private void OnDialogueAdvance(InputAction.CallbackContext ctx)
    {
        // 다음 대화로 진행
    }
}

인벤토리 시스템

public class InventoryUI : MonoBehaviour
{
    public InputLayerController controller;
    
    private void Open()
    {
        controller.PushInputLayer("Inventory"); // 플레이어 이동 입력이 자동으로 차단됨
    }

    private void Close()
    {
        controller.PopInputLayer(); // 플레이어 이동 입력 재개
    }
}

디버그 모드

InputManager의 인스펙터에서 Debug 옵션을 활성화하면 게임 화면 좌측 상단에 현재 레이어 스택이 표시됩니다.

  • 노란색: Root 레이어
  • 초록색: 현재 활성 레이어 (최상단)
  • 흰색: 비활성 레이어

아키텍처

레이어 스택 구조

스택의 최상위에 위치한 입력 레이어만 입력이 활성화됩니다.

루트 입력 레이어는 제거하거나 실행 도중에 변경이 불가능합니다.

┌─────────────────┐
│   UI Layer      │ ← 현재 활성 (입력 받음)
├─────────────────┤
│  Player Layer   │ ← 비활성
├─────────────────┤
│  Root Layer     │ ← 절대 제거 불가
└─────────────────┘

입력 우선순위

InputReceiver의 입력 읽기 메서드(ReadInput, ReadButton 등)는 다음 우선순위에 따라 동작합니다:

  1. 입력 차단 확인: inputBlock이 true면 모든 입력 차단
  2. 레이어 매칭 확인: InputReceiver의 레이어가 현재 최상단 레이어(peekInputLayer)와 일치하지 않으면 입력 무시
  3. 입력 처리: 최상단 레이어의 InputReceiver만 입력을 읽을 수 있음

중요: 콜백(RegisterInputAction)은 이 우선순위 규칙을 따르지 않고, 해당 Input Action이 활성화되어 있으면 항상 호출됩니다.

라이선스

MIT License

기여

이슈와 풀 리퀘스트를 환영합니다!

About

유니티의 입력 시스템을 레이어 구조로 다뤄 입력을 처리

Topics

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE.meta

Stars

Watchers

Forks

Releases

No releases published

Contributors

Languages