---
title: "눌리는 것은 전부 같은 상태 다섯 개를 쓴다"
description: "시안의 버튼은 보통 기본과 눌림 두 장이지만 Unity 는 다섯 상태를 요구합니다. 상태와 전환 방식, 무엇이 클릭을 먹는지, 그룹 전체를 못 누르게 막는 법, 최소 터치 크기를 그림으로 봅니다."
author: "유니얼"
pubDate: 2026-09-17
category: "game-dev/unity/ui"
tags: ["Unity", "UI", "uGUI"]
canonical: https://blog.unialgames.com/posts/unity-ui-selectable-states/
---
시안에서 버튼은 보통 두 장입니다. 평소 모습과 눌렸을 때 모습입니다. Unity 의 버튼은 **상태가 다섯 개** 이고, 그 다섯은 버튼만의 것도 아닙니다.

## 눌리는 것은 전부 한 부모에서 나옵니다

<figure class="diagram">
<svg viewBox="0 0 680 250" role="img" aria-label="버튼, 토글, 슬라이더, 스크롤바, 드롭다운이 모두 Selectable 을 상속해서 상태 다섯 개와 전환 방식을 같이 쓴다">
<rect x="240" y="26" width="200" height="54" rx="8" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="340" y="49" font-size="14" text-anchor="middle" fill="var(--text)">Selectable</text>
<text x="340" y="68" font-size="11" text-anchor="middle" fill="var(--text-muted)">상태 다섯 개와 전환 방식을 가진 부모</text>
<line x1="340" y1="80" x2="340" y2="104" stroke="var(--border)"></line>
<line x1="80" y1="104" x2="80" y2="128" stroke="var(--border)"></line>
<rect x="24" y="128" width="112" height="40" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="80" y="153" font-size="12" text-anchor="middle" fill="var(--text)">Button</text>
<line x1="340" y1="80" x2="340" y2="104" stroke="var(--border)"></line>
<line x1="212" y1="104" x2="212" y2="128" stroke="var(--border)"></line>
<rect x="156" y="128" width="112" height="40" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="212" y="153" font-size="12" text-anchor="middle" fill="var(--text)">Toggle</text>
<line x1="340" y1="80" x2="340" y2="104" stroke="var(--border)"></line>
<line x1="344" y1="104" x2="344" y2="128" stroke="var(--border)"></line>
<rect x="288" y="128" width="112" height="40" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="344" y="153" font-size="12" text-anchor="middle" fill="var(--text)">Slider</text>
<line x1="340" y1="80" x2="340" y2="104" stroke="var(--border)"></line>
<line x1="476" y1="104" x2="476" y2="128" stroke="var(--border)"></line>
<rect x="420" y="128" width="112" height="40" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="476" y="153" font-size="12" text-anchor="middle" fill="var(--text)">Scrollbar</text>
<line x1="340" y1="80" x2="340" y2="104" stroke="var(--border)"></line>
<line x1="608" y1="104" x2="608" y2="128" stroke="var(--border)"></line>
<rect x="552" y="128" width="112" height="40" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="608" y="153" font-size="12" text-anchor="middle" fill="var(--text)">Dropdown</text>
<line x1="80" y1="104" x2="620" y2="104" stroke="var(--border)"></line>
<text x="24" y="200" font-size="12" fill="var(--text)">버튼만 상태가 있는 것이 아닙니다. 체크박스도 슬라이더도 드롭다운도 같은 다섯 상태를 씁니다.</text>
<text x="24" y="222" font-size="12" fill="var(--text-muted)">그래서 한 번 정한 상태 규칙을 화면 전체에 그대로 쓸 수 있습니다. 색만 정해 두면 나머지는 따라옵니다.</text>
</svg>
<figcaption>버튼만이 아니라 토글, 슬라이더, 스크롤바, 드롭다운이 같은 상태를 씁니다.</figcaption>
</figure>

버튼, 토글(체크박스), 슬라이더, 스크롤바, 드롭다운은 모두 같은 부모를 상속합니다. 그래서 **상태 다섯 개와 전환 방식이 전부 같습니다.** 버튼 규칙을 한 번 정해 두면 체크박스와 슬라이더 손잡이에도 그대로 적용됩니다.

## 상태 다섯 개

<x-btn>
<script type="application/json">
{
  "label": "버튼의 다섯 가지 상태",
  "text": "시작하기",
  "note": "색 값은 Unity 의 기본값을 그대로 씁니다."
}
</script>
</x-btn>

- **Normal** 은 아무 일도 없을 때입니다
- **Highlighted** 는 마우스를 올려 둔 상태입니다. **손가락으로 쓰는 화면에서는 거의 안 보입니다.** 모바일 전용 화면이라면 여기에 공들일 필요가 없습니다
- **Pressed** 는 누르고 있는 동안입니다
- **Selected** 는 **누르고 손을 뗀 뒤에도 남는 상태** 입니다. 시안에 없는 상태라 가장 자주 사고가 납니다. 버튼 하나를 눌렀는데 그 버튼만 계속 밝게 남아 있다면 이것입니다
- **Disabled** 는 못 누르는 상태입니다

상태에는 **순서가 있습니다.** 못 누르는 상태가 가장 세고, 그다음이 누르는 중, 선택됨, 마우스 올림, 평소 순입니다. 그래서 Interactable 을 끄면 무엇을 하든 Disabled 로 보입니다.

**Selected 를 어떻게 할지 정해 주세요.** 선택지는 셋입니다.

- Normal 과 같은 모습으로 둡니다. 눌러도 티가 안 남습니다. 가장 흔한 선택입니다
- Highlighted 와 같게 둡니다
- 탭 메뉴처럼 **정말로 선택된 상태를 보여 줘야 하는 자리** 면 따로 그립니다

## 전환 방식은 셋 중 하나

- **Color Tint** 는 원본 이미지 색에 상태 색을 곱합니다. 이미지 한 장으로 다섯 상태를 다 만듭니다. 기본값은 평소 흰색, 마우스 올림 245, 누름 200, 선택됨 245, 못 누름 200 에 알파 절반입니다
- **Sprite Swap** 은 상태마다 다른 이미지를 끼웁니다. 모양이나 테두리까지 바꿀 수 있는 대신 **이미지가 상태 수만큼** 필요합니다
- **Animation** 은 상태마다 애니메이션을 재생합니다. 움직임이 필요한 버튼에 씁니다
- **None** 은 아무것도 안 바꿉니다. 눌렀는지 알 수 없으니 소리나 다른 연출이 대신 있어야 합니다

**곱하기라는 점이 중요합니다.** 원본 버튼 이미지가 이미 짙은 남색이면, 마우스를 올렸을 때 밝게 만들고 싶어도 곱하기로는 밝아지지 않습니다. 밝아지는 연출이 필요하면 **밝은 원본에 색을 곱해 어둡게 쓰거나**, Sprite Swap 으로 갑니다.

## 무엇이 클릭을 먹는가

<figure class="diagram">
<svg viewBox="0 0 680 300" role="img" aria-label="클릭이 그래픽의 Raycast Target, 부모 Canvas Group, Selectable 의 Interactable 을 차례로 지나야 버튼이 눌린다">
<text x="24" y="26" font-size="13" fill="var(--text)">화면을 눌렀을 때 지나가는 관문</text>
<rect x="24" y="44" width="200" height="44" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="38" y="71" font-size="13" fill="var(--text)">맨 앞의 그래픽</text>
<text x="240" y="64" font-size="12" fill="var(--text)">Raycast Target 이 켜져 있나</text>
<text x="240" y="82" font-size="11" fill="var(--warn)">꺼져 있으면 뒤로 통과</text>
<line x1="124" y1="88" x2="124" y2="96" stroke="var(--text-muted)"></line><polygon points="119,96 129,96 124,102" fill="var(--text-muted)"></polygon>
<rect x="24" y="102" width="200" height="44" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="38" y="129" font-size="13" fill="var(--text)">부모 Canvas Group</text>
<text x="240" y="122" font-size="12" fill="var(--text)">Blocks Raycasts 와 Interactable</text>
<text x="240" y="140" font-size="11" fill="var(--warn)">막혀 있으면 여기서 끝</text>
<line x1="124" y1="146" x2="124" y2="154" stroke="var(--text-muted)"></line><polygon points="119,154 129,154 124,160" fill="var(--text-muted)"></polygon>
<rect x="24" y="160" width="200" height="44" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<text x="38" y="187" font-size="13" fill="var(--text)">Selectable</text>
<text x="240" y="180" font-size="12" fill="var(--text)">Interactable 이 켜져 있나</text>
<text x="240" y="198" font-size="11" fill="var(--warn)">꺼져 있으면 Disabled 로</text>
<line x1="124" y1="204" x2="124" y2="212" stroke="var(--text-muted)"></line><polygon points="119,212 129,212 124,218" fill="var(--text-muted)"></polygon>
<rect x="24" y="218" width="200" height="44" rx="6" fill="var(--accent-soft)" stroke="var(--accent)"></rect>
<text x="38" y="245" font-size="13" fill="var(--text)">눌림</text>
<text x="240" y="238" font-size="12" fill="var(--text)">버튼이 반응합니다</text>
<text x="24" y="292" font-size="12" fill="var(--text-muted)">투명한 이미지도 Raycast Target 이 켜져 있으면 클릭을 먹습니다. 안 보인다고 안 막는 것이 아닙니다.</text>
</svg>
<figcaption>클릭은 이 관문들을 차례로 지나야 버튼까지 닿습니다.</figcaption>
</figure>

버튼이 안 눌린다는 이야기는 대부분 이 관문 중 하나에서 막힌 것입니다.

- **Raycast Target** 은 그래픽마다 있는 켬/끔입니다. 켜져 있으면 그 그래픽이 클릭을 받고, 꺼져 있으면 클릭이 뒤로 지나갑니다
- **투명해도 막습니다.** 알파를 0 으로 내려 안 보이게 만든 판도 Raycast Target 이 켜져 있으면 그대로 클릭을 먹습니다. 화면 전체를 덮는 판이 이렇게 남아 있으면 그 아래 버튼이 전부 안 눌립니다
- 반대로 **글자나 장식 이미지처럼 눌릴 일이 없는 것들은 Raycast Target 을 꺼 두는 편** 이 좋습니다. 클릭을 확인할 대상이 줄어듭니다
- 모양대로 눌리게 하는 설정도 있습니다. 다만 그러려면 그 이미지를 **읽을 수 있게 두고 아틀라스에서 빼야** 해서 비용이 붙습니다. 동그란 버튼이라도 사각형 판정으로 두는 편이 보통 낫습니다

### 안 보이는 클릭 영역은 `RaycastReceiver` 로 만듭니다 (Unity 6.5)

클릭만 받고 아무것도 안 그리는 자리가 필요할 때가 있습니다. 팝업 뒤를 막는 판, 아이콘보다 넓은 터치 영역, 화면 어딘가를 누르면 닫히는 영역 같은 것들입니다.

- 예전에는 **알파를 0 으로 내린 이미지** 를 깔았습니다. 안 보이지만 그래픽은 그래픽이라 그리는 목록에 그대로 들어갑니다
- **Unity 6.5 부터는 `RaycastReceiver` 컴포넌트가 있습니다.** 아무것도 그리지 않으면서 클릭만 받는 영역입니다. 바뀐 내용에 "그려지지 않는 상호작용 영역" 이라고 적혀 있습니다
- 6.5 보다 낮은 버전이면 알파 0 짜리 이미지를 계속 쓰게 됩니다. **어느 쪽이든 시안에서는 "여기는 눌리는 자리" 라고만 적어 주시면 됩니다**

## 그룹 전체를 못 누르게

팝업을 띄웠는데 뒤 화면 버튼이 눌린다면 **Canvas Group** 이 할 일입니다. 부모에 하나 붙이면 그 아래 전체에 한 번에 걸립니다.

- **Alpha** 는 자식 전체의 투명도에 곱해집니다. 한 덩어리를 통째로 페이드할 때 씁니다
- **Interactable** 을 끄면 그 아래의 버튼과 슬라이더가 전부 못 누르는 상태가 됩니다. 버튼마다 끄고 켤 필요가 없습니다
- **Blocks Raycasts** 를 끄면 그 아래 전체가 클릭을 **통과시킵니다.** 뒤에 있는 것이 대신 눌립니다
- **Ignore Parent Groups** 를 켜면 부모 쪽 Canvas Group 을 무시합니다. 전체를 막아 놓고 그 안에서 한 부분만 살릴 때 씁니다

버튼은 자기 위쪽 부모들의 Canvas Group 을 거슬러 올라가며 확인합니다. 그래서 **팝업 뒤를 막는 일은 판 하나와 Canvas Group 하나로 끝납니다.**

- 뒤 화면 전체에 **Interactable 을 끈 Canvas Group** 을 걸면 뒤 버튼들이 Disabled 처럼 반응하지 않습니다
- 뒤가 어두워지는 연출까지 있다면 **반투명 판 하나를 깔고 그 판이 클릭을 먹게** 두는 것이 더 간단합니다. 그 판은 Raycast Target 만 켜 두면 됩니다

## 작은 버튼은 눌리는 자리를 따로 잡습니다

<figure class="diagram">
<svg viewBox="0 0 680 250" role="img" aria-label="작은 아이콘 버튼은 그림은 그대로 두고 눌리는 영역만 넓혀서 최소 터치 크기를 맞춘다">
<text x="30" y="26" font-size="13" fill="var(--warn)">그림 크기 = 판정 크기</text>
<rect x="30" y="44" width="120" height="120" rx="8" fill="none" stroke="var(--border)" stroke-dasharray="4 3"></rect>
<rect x="66" y="80" width="48" height="48" rx="8" fill="var(--accent-soft)" stroke="var(--accent)"></rect>
<text x="90" y="110" font-size="14" text-anchor="middle" fill="var(--text)">×</text>
<rect x="66" y="80" width="48" height="48" rx="8" fill="none" stroke="var(--warn)" stroke-width="2"></rect>
<text x="30" y="188" font-size="12" fill="var(--warn)">48 × 48 만 눌립니다</text>
<text x="30" y="208" font-size="11" fill="var(--text-muted)">손가락으로는 자주 빗나갑니다</text>
<text x="250" y="26" font-size="13" fill="var(--accent2)">그림은 그대로, 판정만 넓게</text>
<rect x="250" y="44" width="120" height="120" rx="8" fill="none" stroke="var(--border)" stroke-dasharray="4 3"></rect>
<rect x="250" y="44" width="120" height="120" rx="8" fill="var(--accent2)" fill-opacity="0.12" stroke="var(--accent2)" stroke-width="2"></rect>
<rect x="286" y="80" width="48" height="48" rx="8" fill="var(--accent-soft)" stroke="var(--accent)"></rect>
<text x="310" y="110" font-size="14" text-anchor="middle" fill="var(--text)">×</text>
<text x="250" y="188" font-size="12" fill="var(--accent2)">보이는 것은 48, 눌리는 것은 120</text>
<text x="250" y="208" font-size="11" fill="var(--text-muted)">클릭만 받는 컴포넌트를 깔거나 판정 여백으로</text>
<text x="440" y="70" font-size="13" fill="var(--text)">권장 최소 크기</text>
<text x="440" y="96" font-size="12" fill="var(--text-muted)">iOS 는 44 포인트</text>
<text x="440" y="116" font-size="12" fill="var(--text-muted)">안드로이드는 48 dp</text>
<text x="440" y="142" font-size="12" fill="var(--text)">Unity 가 강제하지는 않습니다</text>
<text x="440" y="162" font-size="12" fill="var(--text-muted)">시안에서 정해 주셔야 합니다</text>
<text x="30" y="238" font-size="12" fill="var(--text-muted)">아이콘을 키우지 않고도 눌리는 자리는 넓힐 수 있습니다. 시안에는 보이는 크기와 눌리는 크기를 같이 적어 주세요.</text>
</svg>
<figcaption>아이콘은 그대로 두고 눌리는 영역만 넓힐 수 있습니다.</figcaption>
</figure>

닫기 버튼이나 아이콘 버튼처럼 작은 것들은 **보이는 크기와 눌리는 크기를 나눠서** 잡습니다. 아이콘은 그대로 두고 눌리는 영역만 넓히면 됩니다.

- 방법은 두 가지입니다. **클릭만 받는 판을 아이콘보다 크게 깔거나**(6.5 부터는 `RaycastReceiver`, 그 전에는 알파 0 이미지), 그래픽의 판정 여백 값을 조절해 영역을 넓힙니다
- 권장 최소 크기는 iOS 가 44 포인트, 안드로이드가 48 dp 입니다. **Unity 가 강제하지 않으니 시안에서 정해 주셔야 합니다**
- 시안에 아이콘 크기만 있으면 아이콘 크기가 그대로 판정이 됩니다. **보이는 크기와 눌리는 크기를 같이 적어 주세요**

## 시안을 넘길 때 적어 주면 좋은 것

| 항목 | 적어 줄 것 |
| --- | --- |
| 상태 | 평소, 누름, 못 누름은 필수. 마우스 올림과 선택됨을 어떻게 할지 |
| 전환 방식 | 색만 바뀌는지, 상태마다 다른 그림인지, 움직이는지 |
| 색 계산 | 색으로 간다면 원본 이미지가 밝은 색인지. 곱하기라 밝게는 못 만듭니다 |
| 못 누르는 모습 | 색만 어두워지는지, 회색으로 바뀌는지, 문구가 바뀌는지 |
| 눌리는 크기 | 보이는 크기와 눌리는 크기. 작은 아이콘 버튼은 특히 |
| 안 보이는 영역 | 눌리기만 하고 안 보이는 자리가 있는지 (팝업 뒤, 닫히는 영역) |
| 팝업 | 팝업이 떴을 때 뒤 화면을 누를 수 있는지, 뒤가 어두워지는지 |
| 소리와 진동 | 누를 때 무엇이 같이 나가는지 |

## 정리

- 버튼, 토글, 슬라이더, 스크롤바, 드롭다운은 같은 부모를 써서 상태 다섯 개가 전부 같습니다
- 상태는 평소, 마우스 올림, 누름, 선택됨, 못 누름이고 못 누름이 가장 셉니다
- 시안에 없는 상태는 대개 선택됨입니다. 누른 뒤에도 남기 때문에 어떻게 할지 정해야 합니다
- 전환은 색 곱하기, 이미지 교체, 애니메이션 중 하나입니다. 곱하기로는 밝게 못 만듭니다
- 클릭은 Raycast Target, Canvas Group, Interactable 순서로 걸러집니다. 투명한 판도 켜져 있으면 클릭을 먹습니다
- 안 보이는 클릭 영역은 Unity 6.5 부터 `RaycastReceiver` 로 만듭니다. 그 전에는 알파 0 짜리 이미지를 깔았습니다
- 팝업 뒤를 막는 일은 판 하나와 Canvas Group 하나로 끝납니다
- 작은 버튼은 보이는 크기와 눌리는 크기를 따로 잡습니다. 권장 최소 크기는 44 포인트, 48 dp 입니다