- 핵심 질문
- 보석에 닿았다는 사실을 코드는 어떻게 알까요?
- 학습 방식
- 예측 → 관찰 → 코드로 설명
- 이전 학습
- Start·Update · 조건문 · 물리 이동
- 핵심 개념
- 이벤트 · 매개변수 · 자신과 상대
- 수업 시간
- 핵심 설명과 시연 50분
- 도착점
- 수집 과정 설명 · 안내 구역에 적용
4주차에는 키보드 입력으로 Player를 움직이고, 발판 위에 착지하게 만들었습니다. 이제 그 움직임이 장면에 변화를 남길 차례입니다. 이번 시간에는 보석에 닿은 순간을 Unity가 감지하고, 코드가 수집 반응을 실행하는 과정을 배웁니다. 보석 하나를 통해 접촉을 감지하는 쪽, 코드를 실행하는 오브젝트, 들어온 상대를 차례로 구분해 봅시다.
- 이전 장면에서 준비
4주차 장면을 이어 받아 보석 하나를 놓습니다.
- 막힘과 통과
Is Trigger를 끄고 켜며 이동의 차이를 관찰합니다.
- 접촉 로그와 설정 테스트
1단계 코드로 진입을 기록하고, 설정을 하나씩 바꾸며 비교합니다.
- 관찰한 로그 해석
누가 메서드를 호출하고, other에 무엇을 전달하는지 읽습니다.
- 대상 확인과 수집
2·3단계에서 Player 확인과 보석 비활성화를 추가합니다.
- return으로 정리
4단계 코드의 실행 순서를 읽고 수집 결과를 확인합니다.
- 실패와 복구
Tag를 바꾸어 오류를 만든 뒤, 로그를 근거로 복구합니다.
- 안내 구역에 적용
바꿀 코드를 예측하고 안내 구역의 반응을 확인합니다.
- 정리와 다음 교시
세 질문으로 복습하고 다음 교시의 시작 상태를 확인합니다.
각 단계에서는 결과를 먼저 예상하고 시연으로 확인합니다. 네 단계 모두 같은 Collectible.cs 파일의 내용을 차례로 교체합니다. 이전 코드를 별도 파일로 남기면 같은 이름의 class가 중복되므로, 한 파일에서 이어 갑니다. 직접 레벨을 만드는 실습은 3교시에 진행합니다. 접힌 보충 자료와 안내 구역 제작 절차는 복습할 때 활용하세요.
4주차 장면에 보석 하나를 놓습니다
접촉을 비교할 장면 준비하기
Trigger 이벤트에는 양쪽의 Collider2D, 한쪽 이상의 Rigidbody2D, 한쪽 이상의 Is Trigger 설정이 필요합니다. 먼저 Player와 보석을 준비하고, 첫 접촉 로그를 만든 뒤 설정을 하나씩 바꾸는 테스트로 결과를 비교합니다.
보충 · 2D와 3D의 차이
이 수업에서는 OnTriggerEnter2D, Collider2D, Rigidbody2D를 사용합니다. 3D에서는 OnTriggerEnter, Collider, Rigidbody를 사용합니다. 두 물리 시스템은 별개이므로 2D와 3D 컴포넌트끼리는 접촉을 감지하지 못합니다.
기존 장면에서 컴포넌트 준비하기
Scene을 다른 이름으로 저장하기
수업 프로젝트 GameEngineI에서
Assets/Week4/Week04_JumpCourse.unity를 엽니다. Play를 종료한 뒤 File → Save As를 선택해Assets/Scenes/Week05_MicroLevel.unity로 저장합니다. 기존 캐릭터 스프라이트와 PlayerController, Move·Jump 참조는 그대로 사용합니다.확인이동·점프·착지가 이전과 같습니다.Player의 Collider2D와 Rigidbody2D 확인하기
Hierarchy에서 Player를 선택하고 Inspector의 기존 Collider2D와 Rigidbody 2D를 확인합니다. Collider2D의 체크박스와 Rigidbody 2D의 Simulated는 켜고, Is Trigger는 끕니다. Rigidbody 2D는 Body Type Dynamic, Gravity Scale 1을 유지합니다. 컴포넌트가 없다면 Add Component에서 필요한 2D 컴포넌트를 검색해 추가합니다. 이미 있다면 중복으로 추가하지 않습니다.
확인Player에 활성화된 Collider2D와 Rigidbody2D가 함께 있습니다.보석과 접촉 경계 준비하기
Project 창의 기존
Collectible.prefab을 Scene으로 하나 끌어옵니다. Hierarchy에서 이름을Collectible로 지정합니다. Inspector에 Box Collider 2D가 없다면 Add Component → Box Collider 2D로 추가합니다. 다음 비교를 위해 처음에는 Is Trigger를 끈 상태로 둡니다. 보석의 그림과 색은 유지합니다.확인이전에 사용한 보석과 Collider 경계가 보입니다.접촉을 관찰할 위치에 배치하기
보석을 평평한 바닥 위에 놓습니다. Player가 옆으로 걸어가면 닿을 수 있고, 시작할 때는 서로 떨어져 있어야 합니다. 보석이 바닥에 묻히거나 점프해야 닿는 위치라면, 첫 비교가 쉬운 곳으로 옮깁니다.
확인시작할 때는 영역 밖에 있고, 걸어가면 안으로 들어옵니다.
수업 프로젝트의 보석 Prefab 경로는 Assets/Week2/Prefabs/Collectible.prefab입니다. 폴더를 다르게 정리했다면 같은 보석 Prefab을 찾아 사용하세요. 이번 설정은 Scene에 놓은 오브젝트에만 추가합니다. Transform의 Scale은 물체의 크기를, Box Collider 2D의 Size와 Offset은 접촉 경계의 크기와 중심을 바꿉니다. 투명한 여백까지 경계에 포함되면 Edit Collider로 보석에 맞춥니다.
| 대상 | Collider2D | Rigidbody2D | Is Trigger |
|---|---|---|---|
| Player | 기존 Collider2D 유지 | 있음 · Dynamic, Gravity Scale 1, Simulated 켬 | 끔 |
| Collectible | Box Collider 2D | 추가하지 않음 · Player 쪽에 있음 | 비교 전 끔 → 비교 후 켬 |
| 바닥·발판·벽 | 기존 Collider2D 유지 | 추가하지 않음 | 끔 · 착지와 차단 유지 |
Player와 Collectible 양쪽에 Collider2D가 있고, Player에는 Rigidbody2D도 있는지 확인합니다. 두 오브젝트가 떨어진 상태에서 시작합니다. 다음 비교를 마치면 Collectible의 Is Trigger를 켜서 세 가지 조건을 모두 갖춥니다.
Is Trigger 하나만 바꾸어 결과를 비교합니다

같은 보석이라도 접촉 경계를 어떻게 설정하느냐에 따라 Player의 움직임이 달라집니다. 이번에는 Collectible의 Is Trigger 하나만 바꿉니다. 보석의 모양과 위치는 유지하고, 앞에서 배치한 보석으로 두 결과를 비교합니다.
A · Is Trigger를 끄고 접근하기
Play를 시작하고 Player를 보석의 옆면으로 이동시킵니다. 경계에서 막히는지 확인한 뒤 Play를 종료합니다.
확인충돌 경계에서 이동이 제한됩니다.B · Is Trigger를 켜고 접근하기
Collectible의 Box Collider 2D에서 Is Trigger를 켭니다. 다시 Play를 시작하고 같은 방향으로 보석에 접근합니다.
확인Player가 통과하며 수집물은 그대로 보입니다.비교를 마치고 설정 저장하기
비교가 끝나면 Play를 종료합니다. Player와 바닥의 Collider는 유지하고, Collectible의 Is Trigger를 켠 상태로 Scene을 저장합니다.
확인Collectible만 통과할 수 있고, 바닥과 발판에는 계속 착지합니다.
일반 충돌이 발생했을 때는 OnCollisionEnter2D(Collision2D collision)로 알림을 받을 수 있습니다. 이번 수집물은 통과할 수 있어야 하므로 OnTriggerEnter2D(Collider2D other)를 사용합니다. 두 메서드는 이름과 매개변수의 자료형이 다릅니다. 이제 화면에서 확인한 진입을 Console에도 기록해 봅시다.
1단계 · 접촉을 로그로 확인합니다
보석을 지나간 순간을 Console에 남겨 봅시다. 첫 코드는 접촉을 기록하는 일만 합니다. 어느 오브젝트의 코드가 실행됐고, 어떤 상대가 들어왔는지를 로그 한 줄로 확인합니다.
Collectible.cs 만들기
Play가 종료된 상태에서 Assets/Scripts에
Collectible.cs를 만듭니다. 파일 내용을 아래 전체 코드로 교체합니다. 기본으로 생성된 Start·Update가 있다면 함께 지우고 아래 코드만 남깁니다.확인파일 이름과 class 이름이 Collectible로 같습니다.보석에 스크립트 붙이기
파일을 저장하고 Unity의 컴파일 오류가 없는지 확인합니다. Hierarchy에서 Collectible을 선택한 뒤 Collectible.cs를 Inspector에 추가합니다. 이번 코드를 실행할 오브젝트는 보석이므로 스크립트도 보석에 붙입니다.
확인수집물에 Sprite Renderer, Box Collider 2D, Collectible 컴포넌트가 있습니다.
OnTriggerEnter2D다른 Collider2D가 Trigger 영역에 들어올 때 Unity가 호출하는 메서드입니다.
호출 전 확인: 양쪽 Collider2D · 한쪽 이상의 Rigidbody2D · 한쪽 이상의 Is Trigger 켬을 확인합니다. 이 장면에서는 Player의 Rigidbody2D와 Collectible의 Trigger를 사용합니다.
대상 읽기: gameObject는 이 스크립트가 붙은 오브젝트, other는 이번에 들어온 상대의 Collider를 가리킵니다.
using UnityEngine;
public class Collectible : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("[접촉] 자신: " + gameObject.name + " / 상대: " + other.name);
}
}Console 준비하기
Console을 열고 검색어를 지웁니다. 일반 Log 표시를 켜고 Clear를 누릅니다. 같은 메시지도 한 줄씩 볼 수 있도록 Collapse는 끕니다.
확인같은 메시지가 나와도 진입할 때마다 한 줄씩 보입니다.영역 밖에서 안으로 들어오기
Play를 시작하고 Player를 보석의 Collider 안으로 이동시킵니다.
확인[접촉] 자신: Collectible / 상대: Player 한 줄이 나옵니다.머무를 때와 다시 들어올 때 비교하기
영역 안에 잠시 머물러 봅니다. 이어서 완전히 밖으로 나갔다가 다시 들어옵니다.
확인머무는 동안 추가 Enter 로그는 없고 재진입할 때 한 줄 더 나옵니다.
[접촉] 자신: Collectible / 상대: Player [접촉] 자신: Collectible / 상대: Player
| 상태 | 새 Enter 호출 | 누적 로그 |
|---|---|---|
| 아직 밖 | 없음 | 0 |
| 첫 진입 | 있음 | 1 |
| 안에 머묾 | 없음 | 1 |
| 완전히 나감 | 없음 | 1 |
| 재진입 | 있음 | 2 |
Enter는 영역에 들어오는 순간을 뜻합니다. 같은 오브젝트도 밖으로 나갔다가 다시 들어오면 새 로그를 남깁니다. 확인을 마치면 Play를 종료합니다. 이제 이 정상 결과를 기준으로 물리 설정을 하나씩 바꿔 봅시다.
보충 · Stay와 Exit는 언제 쓰나요?
OnTriggerStay2D는 영역에 머무는 동안의 처리에, OnTriggerExit2D는 영역을 벗어날 때의 처리에 사용합니다. 이번 수집에서는 진입 순간을 알리는 Enter를 사용합니다. Player에 Collider가 여러 개 있으면 한 번 지나갈 때도 접촉이 여러 번 발생할 수 있으므로, 첫 비교에서는 Collider 하나를 기준으로 관찰합니다.
설정을 하나씩 바꾸며 접촉을 테스트합니다
앞에서 만든 1단계 코드를 그대로 사용합니다. 각 테스트는 Play를 종료한 상태에서 시작합니다. 설정 하나만 바꾸고 Console을 비운 뒤 새 Play로 비교합니다. 확인이 끝나면 Play를 종료하고 바꾼 설정을 복구합니다.
A · 보석의 Collider2D를 끄고 접근하기
Collectible의 Box Collider 2D 제목 왼쪽 체크박스를 끕니다. Sprite Renderer와 Is Trigger 값은 유지합니다. Play를 시작하고 Player로 보석을 통과합니다. 확인 후 Play를 종료하고 Box Collider 2D를 다시 켭니다.
확인보석은 보이지만 [접촉] 로그가 나오지 않습니다.B · Rigidbody2D의 Simulated를 끄고 겹쳐 보기
Player의 Rigidbody 2D에서 Simulated만 끕니다. Play를 시작하면 물리 이동이 멈춥니다. Scene 뷰의 이동 도구로 Player를 보석과 겹쳐 봅니다. 확인 후 Play를 종료하고 Simulated를 다시 켭니다.
확인그림을 겹쳐도 [접촉] 로그가 나오지 않습니다.C · Is Trigger를 끄고 접근하기
Collectible의 Box Collider 2D는 켠 채 Is Trigger만 끕니다. Play를 시작하고 Player로 보석의 옆면에 접근합니다. 확인 후 Play를 종료하고 Is Trigger를 다시 켭니다.
확인보석의 경계에 막히고, [접촉] 로그는 나오지 않습니다.설정을 복구하고 다시 통과하기
양쪽 Collider2D와 Player의 Simulated가 켜져 있는지 확인합니다. Is Trigger는 보석에서만 켭니다. Console을 비우고 Play를 시작해 보석에 들어갑니다. 확인 후 Play를 종료하고 Scene을 저장합니다.
확인보석을 통과할 때 [접촉] 로그가 다시 나옵니다.
B에서는 Rigidbody2D를 삭제하지 않고 물리 참여 여부를 비교했습니다. Simulated를 끄면 Rigidbody2D와 연결된 Collider2D가 함께 물리 계산에서 제외됩니다. 이번 장면에서는 Player의 Rigidbody2D가 한쪽 몸체 조건을 충족하므로 보석에 Rigidbody2D를 추가하지 않습니다.
Player의 이동·점프·착지가 돌아왔고, 보석에 들어가면 접촉 로그가 나옵니다. 이제 로그에 나온 두 이름이 코드의 어느 부분에서 왔는지 살펴봅시다.
로그에 나온 자신과 상대를 구분합니다
로그는 Player가 들어올 때마다 한 줄씩 나왔습니다. Unity가 진입을 감지해 OnTriggerEnter2D를 호출했기 때문입니다. 3주차의 Start와 Update도 Unity가 정해진 시점에 호출했습니다. 이번에는 그 시점이 Trigger 영역에 들어오는 순간입니다. 이처럼 사건이 발생했을 때 Unity가 호출하는 메서드를 이벤트 콜백이라고 부릅니다.
| 메서드 | 호출하는 쪽 | 호출 계기 | 이번 역할 |
|---|---|---|---|
Start() | Unity | 일반적인 실행에서 첫 Update 전 초기화 시점 | 시작 준비 |
Update() | Unity | 활성화된 스크립트의 매 프레임 | 계속 확인할 작업 |
OnTriggerEnter2D(other) | Unity | 다른 Collider2D가 Trigger 영역에 진입 | 접촉 상대에 맞는 반응 |
OnTriggerEnter2D는 class 안에서 다른 메서드와 나란히 정의합니다. Update 안에서 직접 호출할 필요는 없습니다. Unity가 호출할 수 있도록 메서드 이름의 철자·대소문자·2D 표기와 매개변수 자료형을 정확히 작성합니다.
- 01접촉 감지
Unity의 2D 물리 시스템이 영역으로 들어온 Collider를 감지합니다.
- 02콜백 호출
Unity가 메서드를 호출하며 상대 Collider를 전달합니다.
- 03게임의 반응
메서드 안의 코드가 상대를 확인하고 정해 둔 반응을 실행합니다.
로그에서 “자신”은 스크립트가 붙은 Collectible이고, “상대”는 들어온 Player입니다. gameObject.name으로 자신의 이름을, other.name으로 상대 Collider가 붙은 오브젝트의 이름을 읽습니다. +는 이 이름들을 문자열에 이어 붙입니다. 먼저 스크립트가 붙은 위치를 짚으면 두 이름을 구분하기 쉽습니다.

gameObject는 Collectible을, other는 Player의 Collider를 가리킵니다. 따라서 other.gameObject는 Player입니다. 케이블은 상대 정보가 전달되는 관계를 표현한 것이며, 실습에서는 Collider2D를 사용합니다.Collider2D other · 들어온 상대를 받는 매개변수
| 부분 | 뜻 | 확인할 것 |
|---|---|---|
private void | 접근 범위와 반환 형식 | 결과값을 돌려주지 않는 콜백 |
OnTriggerEnter2D | Unity가 호출할 메서드 이름 | 철자·대소문자·2D 표기 |
Collider2D | 매개변수의 자료형 | 상대의 Collider 참조를 받음 |
other | 받은 참조를 코드에서 부를 이름 | Inspector에 직접 연결하는 필드가 아님 |
other에는 이번에 들어온 상대의 Collider가 전달됩니다. Player가 들어오면 Player의 Collider를, 다른 물체가 들어오면 그 물체의 Collider를 받습니다. 매개변수 이름은 바꿀 수 있지만 메서드 안에서 사용하는 이름도 함께 바꿔야 합니다. 이번에는 other로 통일합니다.
| 위치 | 볼 항목 | 판단 |
|---|---|---|
| 왼쪽 Hierarchy | 선택된 Collectible | 스크립트가 붙어야 하는 대상 |
| 가운데 Scene | 보석 그림과 선택된 Collider 경계 | Player가 어느 범위에 들어오면 닿는가 |
| 오른쪽 Inspector | Box Collider 2D의 Is Trigger, Collectible 컴포넌트 | 통과형 경계와 실행할 코드가 함께 있는가 |
로그의 “자신: Collectible / 상대: Player”를 보며 gameObject와 other가 가리키는 대상을 각각 짚어 보세요. 지금 코드는 들어온 상대를 모두 기록합니다. 다음 단계에서는 other의 Tag를 확인해 Player의 접촉을 구분합니다.
2단계 · Player의 접촉을 구분합니다
접촉을 알게 되었으니 수집의 규칙을 정할 차례입니다. 이번 규칙은 “Player가 들어왔을 때만 반응한다”입니다. 3주차에 배운 if로 상대의 Tag를 확인합니다. 이 단계에서는 확인 로그까지만 출력하고 보석은 남겨 둡니다.
Tag코드에서 오브젝트의 역할을 구분할 때 사용하는 표식입니다.
GameObject 이름과 Tag는 따로 설정하는 항목입니다. 이름이 Player여도 Tag가 Untagged이면 CompareTag("Player")는 false입니다. Player Tag는 Trigger가 호출되기 위한 조건이 아니라, 들어온 상대를 코드에서 구분하기 위한 조건입니다.
Inspector에서 Player Tag 설정하기

Play를 종료하고 Player 선택하기
Play 버튼을 눌러 실행을 종료합니다. Project 창의 스크립트나 보석 대신 Hierarchy의 Player 오브젝트를 선택합니다. Inspector에 Player의 이름과 Collider2D, Rigidbody 2D가 보이는지 확인합니다.
확인Player 오브젝트의 Inspector를 보고 있습니다.이름 아래의 Tag 드롭다운 열기
Inspector 맨 위에서 오브젝트 이름 바로 아래에 있는 Tag를 찾습니다. 보통 현재 값은
Untagged입니다. 그 드롭다운을 클릭합니다. 옆의 Layer나 Add Component가 아니라 Tag 항목을 엽니다.확인Untagged, Player 등이 있는 태그 목록이 열립니다.기본 제공되는 Player 선택하기
목록에서 대문자 P로 시작하는
Player를 선택합니다. Player는 Unity의 기본 태그이므로 Add Tag…로 새로 만들 필요가 없습니다. 목록이 닫힌 뒤 Tag 칸에 Player가 표시되는지 확인합니다.확인오브젝트의 이름과 별개로 Tag 값이 Player입니다.선택을 바꾸었다가 다시 확인하고 저장하기
Hierarchy에서 Collectible을 선택했다가 Player를 다시 선택합니다. Player의 Tag가 Player로 유지되면 File → Save로 Scene을 저장합니다. Play 중 변경한 값은 실행을 종료하면 돌아갈 수 있으므로, 태그 설정과 저장은 Play를 종료한 상태에서 합니다.
확인저장한 Scene에서 Player의 Tag가 Player로 남아 있습니다.
other.CompareTag("Player")는 들어온 Collider2D가 붙은 GameObject의 Tag를 확인합니다. 부모의 Tag는 자식에게 자동으로 적용되지 않습니다. Collider2D가 자식에 있다면 그 자식도 선택해 Player Tag를 확인하세요. 이번 기본 실습은 Player 오브젝트에 Collider2D와 Rigidbody2D가 함께 있는 구성을 사용합니다.
보충 · Add Tag…는 언제 사용하나요?
Enemy처럼 새 태그가 필요할 때 사용합니다. Tag → Add Tag…에서 Tags 목록의 + 버튼을 누르고 이름을 입력해 저장합니다. 태그를 만드는 것과 오브젝트에 지정하는 것은 별도 단계입니다. Hierarchy에서 대상 오브젝트를 다시 선택한 뒤 Tag 드롭다운에서 방금 만든 태그를 선택해야 적용됩니다. 기본 태그인 Player는 Tags 관리 목록에 없어도 오브젝트의 Tag 드롭다운에서 선택할 수 있습니다.
같은 파일에 조건문 추가하기
태그 설정을 마쳤다면 같은 Collectible.cs 파일을 아래 전체 코드로 교체하고 저장합니다. Unity에서 컴파일이 끝났는지 확인합니다. 보석에 붙어 있는 Collectible 컴포넌트 하나를 계속 사용합니다. 첫 [접촉] 로그 다음에 조건문과 [확인] 로그가 추가됩니다.
CompareTagother.CompareTag("Player")는 상대의 Tag가 Player인지 확인해, 같으면 true, 다르면 false를 반환합니다.
using UnityEngine;
public class Collectible : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("[접촉] 자신: " + gameObject.name + " / 상대: " + other.name);
if (other.CompareTag("Player"))
{
Debug.Log("[확인] Player Tag");
}
}
}비교 결과가 true일 때는 if의 중괄호 안을 실행합니다. false일 때는 그 부분을 건너뛰고 메서드 끝으로 갑니다. 첫 [접촉] 로그는 if 앞에 있으므로 두 경우 모두 출력됩니다.
Player의 Tag를 Player로 둔 채 Console을 비우고 Play를 시작합니다. 보석에 들어가면 [접촉] 다음에 [확인] 로그가 나오고, 보석은 남아 있어야 합니다. 확인한 뒤 Play를 종료합니다.
| 상대의 설정 | 접촉 로그 | 확인 로그 | 수집물 |
|---|---|---|---|
| 이름 Player / Tag Player | 나옴 | 나옴 | 남아 있음 |
| 이름 Hero / Tag Player | 상대 이름 Hero로 나옴 | 나옴 | 남아 있음 |
| 이름 Player / Tag Untagged | 나옴 | 안 나옴 | 남아 있음 |
이름만 Hero로 바꾸거나 Tag만 Untagged로 바꾸면 어느 로그가 달라질까요? 표를 가리고 코드의 순서를 따라 답한 뒤 표와 비교하세요. 지금은 이름과 Tag를 유지합니다. Tag를 실제로 바꾸는 실험은 수집 동작을 완성한 뒤 진행합니다.
이제 코드는 접촉한 상대가 Player인지 구분할 수 있습니다. [확인] 로그가 나온 자리에 보석의 수집 반응을 넣어 봅시다.
3단계 · Player가 닿으면 보석을 수집합니다
이제 Console에서 확인한 접촉을 화면의 변화로 이어 봅시다. if 안의 [확인] 로그를 [수집] 로그로 바꾸고, 바로 다음에 보석 자신을 비활성화하는 한 줄을 추가합니다. Player를 확인하는 조건은 그대로 사용합니다.
Play를 종료하고 Player의 Tag가 Player인지, Collectible의 Is Trigger가 켜져 있는지 확인합니다. 같은 Collectible.cs를 아래 코드로 교체한 뒤 저장하고 컴파일을 기다립니다.
SetActiveGameObject의 활성 상태를 설정하는 메서드로, true는 활성화, false는 비활성화를 뜻합니다.
using UnityEngine;
public class Collectible : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("[접촉] 자신: " + gameObject.name + " / 상대: " + other.name);
if (other.CompareTag("Player"))
{
Debug.Log("[수집] Collectible 비활성화");
gameObject.SetActive(false);
}
}
}접촉 한 번에 실행되는 코드 따라가기
| 순서 | 실행하는 줄 | 결과 |
|---|---|---|
| 1 | 첫 Debug.Log | 자신과 상대의 이름을 출력 |
| 2 | CompareTag("Player") | true → if 안으로 들어감 |
| 3 | 수집 Debug.Log | 수집 처리에 도달했음을 출력 |
| 4 | gameObject.SetActive(false) | Collectible의 그림·Collider 등을 함께 비활성화 |
이 코드에서 gameObject는 Collectible, other.gameObject는 들어온 Player를 가리킵니다. 따라서 gameObject.SetActive(false)는 “Collectible을 비활성화한다”라고 읽습니다. other.gameObject에 이 메서드를 호출하면 Player가 비활성화되므로, 동작과 함께 그 대상도 확인합니다.
로그와 화면의 변화 확인하기
Console을 비우고 Play를 시작합니다. Player를 움직여 보석에 닿게 합니다.
확인접촉 로그 다음에 수집 로그가 나오고 보석이 사라집니다.Hierarchy에서 비활성 상태 확인하기
Play를 유지한 채 Hierarchy에서 Collectible의 이름과 활성 상태를 살펴봅니다.
확인Collectible의 이름이 흐리게 남아 있고, 활성 상태가 꺼져 있습니다.Play를 종료하고 보석 확인하기
Play를 종료한 뒤 Scene에서 보석이 다시 보이는지 확인합니다.
확인보석이 다시 활성화되어 다음 실행을 준비할 수 있습니다.
보충 · 그림만 숨기면 수집 처리가 끝날까요?
| 방법 | 그림 | 접촉 경계 |
|---|---|---|
| Sprite Renderer만 끔 | 보이지 않음 | 남아 있음 |
| Collider2D만 끔 | 남아 있음 | 꺼짐 |
| GameObject를 비활성화 | 보이지 않음 | 함께 꺼짐 |
Sprite Renderer만 끄면 그림은 사라져도 Collider가 남아 접촉이 다시 발생할 수 있습니다. SetActive(false)는 GameObject 전체를 비활성화하므로 그림과 접촉 경계가 함께 꺼집니다. 오브젝트는 Hierarchy에 남아 있어 비활성화와 삭제를 구분할 수 있습니다.
Player의 Tag가 Untagged라면 보석은 남아 있습니다. 이때 [접촉] 로그는 나올까요? if 앞에 있는 코드를 근거로 설명해 보세요. 다음 단계에서는 같은 수집 결과를 유지하면서 조건문의 순서를 정리합니다.
4단계 · Player가 아니면 메서드 실행을 마칩니다
코드가 길어질수록 어느 경우에 실행을 마치는지가 눈에 잘 들어와야 합니다. 이번에는 Player가 아니면 먼저 메서드 실행을 마치는 방식으로 정리합니다. Player인 경우에는 return을 건너뛰고 수집 코드를 실행하므로, 앞 단계와 수집 결과는 같습니다.
Play를 종료한 상태에서 같은 Collectible.cs를 아래 코드로 교체하고 저장합니다. Tag와 Trigger 설정은 유지합니다.
! · return!는 true와 false를 뒤집고, return;은 현재 메서드의 실행을 그 자리에서 마칩니다.
using UnityEngine;
public class Collectible : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("[접촉] 자신: " + gameObject.name + " / 상대: " + other.name);
if (!other.CompareTag("Player"))
{
return;
}
Debug.Log("[수집] Collectible 비활성화");
gameObject.SetActive(false);
}
}| 상대 Tag | CompareTag | !를 붙인 값 | return 실행 | 수집 코드 |
|---|---|---|---|---|
| Player | true | false | 건너뜀 | 실행 |
| Untagged | false | true | 실행 | 도달하지 않음 |
여기서 return이 끝내는 범위는 이번 OnTriggerEnter2D 메서드 실행입니다. Player의 이동과 게임 실행은 계속됩니다. 수집 코드가 if의 중괄호 밖에 있어도, return을 실행한 경우에는 그 아래 줄로 내려가지 않습니다.

return에서 실행을 마칩니다. 아래쪽은 수집 처리까지 이어집니다. 같은 코드도 상대의 Tag에 따라 지나가는 줄이 달라집니다. 그림의 램프는 코드의 실행 여부를 나타냅니다.3주차에서 조건에 따라 메서드의 남은 작업을 건너뛴 것과 같은 방식입니다. 2교시에는 이 부분에 “이미 수집했는가”, “진행 상태 컴포넌트가 있는가”라는 확인을 추가합니다.
표를 보며 Player와 Untagged 각각의 실행 순서를 따라가 보세요. 이어서 컴파일을 확인하고 Console을 비운 뒤 Player Tag로 한 번 실행합니다. [접촉] → [수집] 로그와 보석의 비활성화를 확인하면 Play를 종료합니다. 이 결과를 기준으로 다음 단계의 Tag 오류를 비교합니다.
로그로 실행이 멈춘 곳을 찾습니다
보석을 통과했는데도 그림이 남아 있다면, 실행은 어디까지 진행된 걸까요? 로그에는 코드가 지나온 흔적이 남습니다. 4단계의 [접촉]과 [수집] 로그를 비교하면 메서드가 호출됐는지, 수집 처리까지 도달했는지를 나누어 확인할 수 있습니다.
| 관찰 | 먼저 내릴 판단 | 다음 확인 |
|---|---|---|
| 접촉 로그도 없음 | 콜백 진입을 아직 확인하지 못함 | Console 필터 → 컴파일 오류 → 스크립트 연결 → 양쪽 Collider2D·Rigidbody2D·Is Trigger → 실제 경계 겹침 |
| 접촉 로그만 있음 | 메서드는 호출됨. 수집 줄에는 도달하지 않음 | 접촉 상대 이름 → 상대 Collider2D가 붙은 오브젝트의 Player Tag → 조건문·return |
| 접촉·수집 로그 모두 있음 | 조건을 통과해 수집 처리에 도달함 | SetActive의 대상 → 같은 자리에 다른 그림이 겹쳐 있는지 |
Tag를 바꾸어 오류를 만들고 복구하기
앞 단계에서 확인한 정상 결과를 기준으로 오류를 만들어 봅시다. Play를 종료하고, return 직전에 중단 이유를 출력하는 로그 한 줄을 추가합니다. 아래 관찰용 코드로 교체·저장한 뒤 컴파일을 확인합니다. 이후 두 실행에서는 코드를 유지하고 Player의 Tag만 바꿉니다. Trigger와 컴포넌트 연결도 그대로 둡니다.
관찰용 Collectible.cs 전체 코드
using UnityEngine;
public class Collectible : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("[접촉] 자신: " + gameObject.name + " / 상대: " + other.name);
if (!other.CompareTag("Player"))
{
Debug.Log("[중단] Player Tag가 아닙니다.");
return;
}
Debug.Log("[수집] Collectible 비활성화");
gameObject.SetActive(false);
}
}Tag를 Untagged로 바꾸기
Play가 종료된 상태에서 Player의 Tag를 Untagged로 바꿉니다. Console을 비우고 다시 Play를 시작해 같은 보석에 들어갑니다.
확인[접촉] → [중단], Collectible은 남음실행이 끝난 줄 찾기
[중단] 로그 다음의 return을 찾아보세요. 이 줄에서 메서드 실행이 끝난다는 점을 근거로 [수집] 로그가 나오지 않은 이유를 설명합니다.
확인접촉은 감지됐고, Tag 조건에서 실행을 마쳤습니다.Tag를 복구하고 다시 실행하기
Play를 종료하고 Tag를 Player로 되돌립니다. 관찰용 코드는 유지한 채 Console을 비웁니다. 다시 Play를 시작하고 같은 보석에 들어갑니다.
확인[접촉] → [수집]이 돌아오고 수집물이 비활성화됩니다.
[접촉] 자신: Collectible / 상대: Player [중단] Player Tag가 아닙니다.
접촉은 감지됐습니다. Tag 조건 때문에 return에서 실행을 마쳐 보석이 남습니다.
[접촉] 자신: Collectible / 상대: Player [수집] Collectible 비활성화
수집 처리까지 실행되어 보석이 사라집니다. Hierarchy에는 비활성화된 Collectible의 이름이 흐리게 남습니다.
로그가 없을 때 순서대로 확인하기
먼저 Console의 검색어와 Log 표시, 컴파일 오류를 확인합니다. 이어서 Collectible 스크립트의 연결 위치, 메서드 철자, 두 Collider의 실제 겹침을 살펴봅니다. 마지막으로 Is Trigger, Player Rigidbody2D의 Simulated, Layer의 접촉 설정을 확인합니다. 한 항목씩 확인하고 다시 실행해야 원인을 구분할 수 있습니다.
보충 · 이름·Tag·Layer·Sorting Layer
| 항목 | 역할 |
|---|---|
| 이름 | Hierarchy와 로그에서 대상을 구분 |
| Tag | 코드에서 상대 역할을 확인 |
| Layer | Physics 2D에서 접촉을 허용할 그룹을 지정 |
| Sorting Layer | Sprite가 그려지는 앞뒤 순서를 지정 |
Layer는 4주차의 설정을 사용합니다. 접촉 그룹을 나누는 방법은 2교시의 선택 심화 자료에서 다룹니다.
Play를 종료하고 Player의 Tag를 Player로 되돌립니다. Collectible.cs는 4단계 코드로 복구해 관찰용 [중단] 로그를 정리합니다. Scene과 코드를 저장하고 컴파일 오류가 없는지 확인합니다. 이제 접촉과 대상 확인은 유지한 채, 마지막 반응을 다른 용도로 바꿔 봅시다.
같은 원리로 안내 구역을 만듭니다
보석을 줍는 순간과 길 안내를 받는 순간은 화면에서 서로 다른 경험입니다. 두 장면 모두 Player가 어떤 영역에 들어왔다는 사실에서 시작합니다. 이번에는 Player가 들어오면 안내를 출력하고, 구역은 계속 남아 있는 GuideZone을 생각해 봅시다. 해설을 열기 전에 수집 코드에서 유지할 부분과 바꿀 부분을 구분하세요.
① 구역이 남아 있으려면 어떤 줄을 빼야 할까요? ② 안내 메시지는 Player를 확인하는 조건의 앞과 뒤 중 어디에 둘까요? ③ 처음 들어와 머물 때와, 나갔다가 다시 들어올 때 안내는 각각 몇 번 나올까요?
해설과 적용 코드 · GuideZone.cs

| 항목 | Collectible | GuideZone |
|---|---|---|
| 진입 감지 | OnTriggerEnter2D | 같은 메서드 사용 |
| 대상 | Player Tag | 같은 조건 사용 |
| 반응 | 수집 로그와 자기 비활성화 | 안내 로그만 출력 |
| 재진입 | 비활성화되어 새 접촉 없음 | 구역이 남아 있으므로 다시 안내 |
gameObject.SetActive(false)를 빼고 [수집] 로그를 안내 문장으로 바꿉니다. 안내는 Player 확인을 통과한 뒤에 출력합니다. GuideZone이 활성 상태로 남아 있으므로 재진입할 때도 반응합니다. 첫 진입에 한 번, 머무는 동안에는 추가 출력이 없고, 다시 들어오면 한 번 더 출력됩니다.
using UnityEngine;
public class GuideZone : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
if (!other.CompareTag("Player"))
{
return;
}
Debug.Log("안내: 오른쪽 발판으로 이동하세요.");
}
}예측한 내용을 시연으로 확인하기
미리 준비한 GuideZone을 켜고 Console을 비운 뒤 Play를 시작합니다. Player가 들어와 머무르고, 밖으로 나갔다가 다시 들어오는 모습을 함께 봅시다. 안내가 출력되는 횟수를 예상과 비교하세요. 수업에서는 반응의 차이를 확인하고, 직접 만드는 방법은 아래 절차로 복습합니다.
직접 만들어 보기 · GuideZone 준비와 실행 절차
안내 구역 준비하기
Play를 종료하고 Square로 GuideZone을 만듭니다. Collectible과 떨어진 곳에 배치하고 Box Collider 2D를 추가한 뒤 Is Trigger를 켭니다.
확인수집물과 안내 구역이 분리되어 있습니다.GuideZone 코드 연결하기
새 GuideZone.cs 파일에 위 코드를 작성하고 저장합니다. 컴파일이 끝나면 GuideZone 오브젝트에 붙입니다. Collectible을 복제해 만들었다면 복사본의 Collectible 컴포넌트는 제거합니다.
확인안내 구역에는 GuideZone 스크립트가 하나 붙어 있습니다.들어오기·머무르기·다시 들어오기 비교하기
Player의 Tag가 Player인지 확인하고 Play를 시작합니다. 안내 구역 안에 머문 뒤 완전히 밖으로 나갔다가 다시 들어옵니다.
확인안내는 진입마다 한 번 나오고 구역은 남습니다.
직접 만들어 본 뒤에도 Play를 종료하고 GuideZone을 비활성화합니다. 다음 교시에는 Collectible의 4단계 코드와 정상 설정에서 이어 갑니다.
시연을 마치면 Play를 종료하고 GuideZone을 비활성화합니다. Collectible의 4단계 코드와 정상 설정을 유지한 채 Scene을 저장합니다. 마지막 3분은 핵심 개념과 다음 교시의 준비 상태를 확인하는 데 씁니다.
진입 감지와 Player 확인을 함께 사용해도, 마지막 반응에 따라 구역의 역할이 달라집니다. 수집물과 안내 구역의 재진입 결과를 바꾸는 코드가 무엇인지 설명해 보세요.
세 질문으로 오늘의 코드를 설명합니다
보석 하나를 수집하는 짧은 순간에 접촉 감지, 상대 확인, 반응 실행이 이어졌습니다. 이제 그 과정을 자신의 말로 설명해 봅시다. 아래 세 질문에 먼저 답한 뒤 해설을 열어 확인하세요.
누가 메서드를 호출하고 other에는 무엇이 들어오나요?
Unity가 2D Trigger 영역으로 들어온 Collider를 감지해 메서드를 호출합니다. other는 그 상대 Collider의 참조를 받습니다. 이번 예제에서는 Collectible에 붙은 코드가 Player의 Collider를 전달받았습니다.
접촉 로그만 나오고 수집 로그는 없다면 무엇을 알 수 있나요?
[접촉] 로그가 있으므로 메서드가 호출된 것은 확인할 수 있습니다. [수집] 로그까지 이어지지 않았다면 그 사이의 조건문과 return을 살펴봅니다. 이번 실험에서는 상대의 Tag가 Untagged여서 return에서 실행을 마쳤습니다.
같은 Trigger로 수집물과 안내 구역을 만들 수 있는 이유는?
두 구역 모두 진입을 감지하고 Player인지 확인합니다. 그 뒤에 수집물은 자신을 비활성화하고, 안내 구역은 메시지를 출력합니다. 활성 상태로 남아 있는 안내 구역은 다음 진입에도 반응합니다.
| 대상 | 최종 상태 |
|---|---|
| Scene | Week05_MicroLevel 저장 · Play 종료 |
| Player | 기존 이동·점프 유지 · Collider2D + Rigidbody2D · Tag Player |
| Collectible | Is Trigger 켬 · Collectible 컴포넌트 하나 · 4단계 코드 |
| GuideZone | 적용 시연을 했다면 비활성화 |
| Console | 컴파일 오류 0 · 정상 접촉과 수집 확인 |
보석이 화면에서 사라진 뒤에도 게임은 몇 개를 모았는지 기억해야 합니다. 지금 코드는 수집 개수를 기록하지 않습니다. 2교시에는 수집한 결과를 Player에 남기는 방법을 배웁니다. 오늘의 “접촉 → 상대 확인 → 반응”에 다른 컴포넌트의 메서드를 호출하는 과정을 이어 붙입니다.
Unity 공식 문서
- Rigidbody2D.simulated ↗몸체와 연결된 Collider2D의 물리 시뮬레이션 참여
- Tags · 태그 지정 ↗Inspector의 Tag 위치 · 기본 Player 태그 · 태그 생성과 지정
- OnTriggerEnter2D ↗호출 시점 · 상대 Collider · 필요한 물리 설정
- CompareTag ↗Tag 비교와 true·false 반환
- GameObject.SetActive ↗GameObject와 컴포넌트의 활성 상태
- Layer Collision Matrix ↗Layer 사이의 접촉 허용 설정
