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

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Contributors

Languages