▣ 이전 글에서는
IInteractable
Interface를 이용해서
Player가 문을 바라보면
[E] 문 열기
UI가 나타나고,
E를 누르면 문이 열리고 닫히도록 만들었습니다.
또한
PlayerKeyInventory
를 이용해서
특정 열쇠가 있어야 열 수 있는
잠긴 문도 만들었습니다.
현재 상호작용 시스템의 기본 구조는
FPS Camera
↓
Raycast
↓
IInteractable 확인
↓
Interaction UI 표시
↓
E 입력
↓
Interact()
입니다.
이번 글에서는
이 구조를 그대로 사용해서
새로운 상호작용 Object인
Button
을 만들어보겠습니다.
Player가 버튼을 바라보면
[E] 버튼 누르기
UI가 나타나고
E를 누르면
조명 ON / OFF
GameObject ON / OFF
를 제어하도록 만들겠습니다.
전체 흐름은
Button Object 만들기
↓
Collider 추가
↓
ButtonInteractable 만들기
↓
IInteractable 구현
↓
Light 연결
↓
GameObject 연결
↓
E 입력
↓
Interact()
↓
bool 상태 변경
↓
Light / GameObject ON OFF
순서로 진행하겠습니다.
1. 기존 Interaction 시스템 그대로 사용하기
이번 Button 기능을 위해
Player 쪽 Script를
새로 만들 필요는 없습니다.
앞에서 이미
Player가
IInteractable
을 바라보고 있는지
확인하도록 만들었습니다.
그리고 E를 누르면
다음 코드가 실행됩니다.
playerRaycast
.CurrentInteractable
.Interact();
Player 입장에서는
현재 Object가
Door인지
Button인지
Item인지
알 필요가 없습니다.
단순히
IInteractable인가?
만 확인합니다.
따라서 Button도
IInteractable
을 구현하면
기존 시스템에 바로 연결할 수 있습니다.
2. Button Object 만들기
Hierarchy에서
Cube를 하나 생성합니다.
Hierarchy
↓
3D Object
↓
Cube
이름은
Button
으로 변경하겠습니다.
3. 버튼처럼 크기 조절하기
Cube를 선택하고
Scale을 조절해서
벽에 붙어 있는 버튼처럼 만들어봅니다.
예를 들어
Scale
X = 0.4
Y = 0.4
Z = 0.1
정도로 시작할 수 있습니다.
게임의 Scale에 따라
자유롭게 변경하면 됩니다.
4. 벽에 Button 배치하기
Scene View에서
Button을
Wall 앞쪽에 배치합니다.
예를 들어
Wall
│
│ [ Button ]
│
│
처럼
Player가 가까이 접근해서
바라볼 수 있는 위치에 놓습니다.
5. Collider 확인
Cube로 Button을 만들었다면
기본적으로
Box Collider
가 있습니다.
앞에서 만든 Raycast는
Collider를 감지하기 때문에
Button에도 Collider가 필요합니다.
Button을 선택해서
Box Collider
Enabled
→ 체크
상태인지 확인합니다.
6. 테스트용 조명 만들기
이번에는 Button으로
제어할 조명을 만들어보겠습니다.
Hierarchy에서
다음과 같이 생성합니다.
Create
↓
Light
↓
Point Light
이름은
RoomLight
로 변경하겠습니다.
7. Point Light 배치
RoomLight를
테스트할 공간 안쪽에 배치합니다.
예를 들어
천장 근처에 놓고
Range와 Intensity를 조절합니다.
RoomLight
Type
→ Point
Range
→ 10
Intensity
→ 프로젝트에 맞게 조절
Play Mode에서
빛이 잘 보이는지 확인합니다.
8. GameObject도 하나 준비하기
Button으로
Light뿐 아니라
일반 GameObject도 제어해보겠습니다.
Hierarchy에서
Cube를 하나 더 만듭니다.
이름은
TargetObject
로 하겠습니다.
이 Object는
Button을 눌렀을 때
켜지고 꺼지는지 확인하기 위한
테스트 Object입니다.
9. 이번 Button의 동작
이번 Button은
한 번 누르면
OFF
↓
ON
다시 누르면
ON
↓
OFF
로 동작하게 만들겠습니다.
즉
E
↓
상태 반전
↓
Light ON / OFF
GameObject ON / OFF
구조입니다.
10. ButtonInteractable Script 만들기
Project Window의
Scripts Folder에서
새 C# Script를 만듭니다.
이름은
ButtonInteractable
로 하겠습니다.
11. IInteractable 구현
Button도
Player가 E로 사용할 수 있는 Object이므로
IInteractable
을 구현합니다.
using UnityEngine;
public class ButtonInteractable :
MonoBehaviour,
IInteractable
{
}
이제 앞에서 만든
Raycast 시스템이
Button을 상호작용 대상으로
인식할 수 있습니다.
12. InteractionText 구현
Button을 바라봤을 때
화면에 표시할 문구를 만듭니다.
public string InteractionText
{
get
{
return "버튼 누르기";
}
}
그러면 기존
FPSPlayerInteraction
에서
자동으로
[E] 버튼 누르기
가 표시됩니다.
13. Player UI는 수정하지 않는다
앞에서 만든 코드는
다음 구조였습니다.
interactionText.text =
"[E] " +
playerRaycast
.CurrentInteractable
.InteractionText;
Button이
버튼 누르기
를 반환하면
Player UI에서는
자동으로
[E] 버튼 누르기
가 됩니다.
따라서 Player Script는
이번에도 수정할 필요가 없습니다.
14. 제어할 Light 변수 만들기
Button에서
어떤 Light를 제어할지
알아야 합니다.
다음 변수를 만듭니다.
[SerializeField]
private Light targetLight;
Inspector에서
RoomLight를 연결할 예정입니다.
15. Light Component
Unity의 Light는
다음과 같은 Component입니다.
Point Light
Spot Light
Directional Light
등이 모두
Light
Component를 사용합니다.
따라서
Light targetLight;
하나로
여러 종류의 조명을
연결할 수 있습니다.
16. 제어할 GameObject 변수 만들기
이번에는
일반 GameObject도 하나
연결하겠습니다.
[SerializeField]
private GameObject targetObject;
Inspector에서
앞에서 만든
TargetObject
를 연결합니다.
17. 현재 상태 저장하기
Button이 현재
ON인지 OFF인지
알 수 있도록
bool 변수를 만듭니다.
private bool isOn;
bool
은
두 가지 상태만 저장할 수 있습니다.
false
→ OFF
true
→ ON
으로 사용하겠습니다.
18. 시작 상태 설정
이번에는
Inspector에서
처음 상태를 설정할 수 있도록
다음처럼 만들겠습니다.
[SerializeField]
private bool startOn;
예를 들어
Start On
→ 체크
하면
게임 시작 시
Button이 ON 상태입니다.
체크하지 않으면
OFF 상태입니다.
19. Start에서 상태 초기화
게임이 시작되면
startOn
값을
현재 상태로 저장합니다.
private void Start()
{
isOn = startOn;
}
하지만 여기서 끝내면
Light와 GameObject의 실제 상태가
isOn과 다를 수 있습니다.
따라서
상태를 실제 Object에도
적용해야 합니다.
20. ApplyState Method 만들기
Light와 GameObject 상태를
한 곳에서 처리하도록
Method를 하나 만들겠습니다.
private void ApplyState()
{
}
이 Method 안에서
현재
isOn
값을 보고
Light와 GameObject 상태를
변경하겠습니다.
21. Light ON / OFF
Light Component에는
enabled
Property가 있습니다.
따라서
targetLight.enabled = isOn;
으로
조명을 켜고 끌 수 있습니다.
22. Light enabled 이해하기
현재
isOn = true
라면
targetLight.enabled = true;
가 되어
조명이 켜집니다.
반대로
isOn = false
라면
targetLight.enabled = false;
가 되어
조명이 꺼집니다.
23. Null 확인하기
하지만 Inspector에서
Light를 연결하지 않을 수도 있습니다.
그 상태에서
targetLight.enabled
를 사용하면
오류가 발생할 수 있습니다.
따라서 먼저
확인하겠습니다.
if (
targetLight != null
)
{
targetLight.enabled =
isOn;
}
24. GameObject ON / OFF
GameObject 자체를
켜고 끌 때는
SetActive()
를 사용할 수 있습니다.
targetObject.SetActive(
isOn
);
입니다.
25. SetActive(true)
다음 코드는
targetObject.SetActive(
true
);
GameObject를
활성화합니다.
Hierarchy에서도
Object가 활성 상태가 됩니다.
26. SetActive(false)
반대로
targetObject.SetActive(
false
);
를 사용하면
GameObject가 비활성화됩니다.
Renderer뿐 아니라
해당 GameObject에 붙어 있는
여러 Component도
동작하지 않게 됩니다.
27. GameObject도 Null 확인
Light와 마찬가지로
연결되지 않은 경우를
생각하겠습니다.
if (
targetObject != null
)
{
targetObject.SetActive(
isOn
);
}
28. ApplyState 전체 코드
현재 Method는
다음과 같습니다.
private void ApplyState()
{
if (
targetLight != null
)
{
targetLight.enabled =
isOn;
}
if (
targetObject != null
)
{
targetObject.SetActive(
isOn
);
}
}
29. Start에서 ApplyState 호출
게임 시작과 동시에
startOn 값이
실제 Object에 적용되도록
다음처럼 작성합니다.
private void Start()
{
isOn = startOn;
ApplyState();
}
이제
Inspector의
Start On 값과
Light / GameObject의
실제 상태가 같아집니다.
30. Interact 만들기
Player가 E를 누르면
Button의
Interact()
가 실행됩니다.
public void Interact()
{
}
여기서
현재 ON / OFF 상태를
반대로 바꾸겠습니다.
31. bool 상태 반전
다음 코드를 사용합니다.
isOn = !isOn;
예를 들어
현재
isOn = false
라면
E 입력 후
isOn = true
가 됩니다.
32. 다시 누르면
현재
isOn = true
상태에서
다시 실행하면
isOn = false
가 됩니다.
즉
false
↔
true
를 반복합니다.
33. 상태 변경 후 ApplyState 호출
bool 값만 바꾸면
Light가 자동으로 바뀌는 것은 아닙니다.
따라서
다음 코드를 실행합니다.
ApplyState();
최종 Interact는
public void Interact()
{
isOn = !isOn;
ApplyState();
}
가 됩니다.
34. ButtonInteractable 전체 코드
지금까지 내용을
하나로 정리하겠습니다.
using UnityEngine;
public class ButtonInteractable :
MonoBehaviour,
IInteractable
{
// Button으로 제어할
// Light Component입니다.
[SerializeField]
private Light targetLight;
// Button으로 제어할
// GameObject입니다.
[SerializeField]
private GameObject targetObject;
// 게임 시작 시
// Button이 ON 상태인지 설정합니다.
[SerializeField]
private bool startOn;
// 현재 Button의
// ON / OFF 상태입니다.
private bool isOn;
// Player가 Button을 바라봤을 때
// 표시할 Interaction 문구입니다.
public string InteractionText
{
get
{
return "버튼 누르기";
}
}
private void Start()
{
// Inspector에서 설정한
// 시작 상태를 적용합니다.
isOn = startOn;
ApplyState();
}
// Player가 E를 누르면
// FPSPlayerInteraction에서
// 호출됩니다.
public void Interact()
{
// 현재 상태를
// 반대로 변경합니다.
isOn = !isOn;
// 변경된 상태를
// Light와 GameObject에 적용합니다.
ApplyState();
}
private void ApplyState()
{
// Light가 연결되어 있다면
// 현재 상태에 따라
// Light를 켜거나 끕니다.
if (
targetLight != null
)
{
targetLight.enabled =
isOn;
}
// GameObject가 연결되어 있다면
// 현재 상태에 따라
// 활성 / 비활성 상태로 변경합니다.
if (
targetObject != null
)
{
targetObject.SetActive(
isOn
);
}
}
}
35. Button에 Script 추가
Hierarchy에서
Button을 선택합니다.
ButtonInteractable
Script를 추가합니다.
구조는
Button
│
├─ Mesh Renderer
├─ Box Collider
│
└─ Button Interactable
이 됩니다.
36. Target Light 연결
Button Interactable의
Inspector를 확인합니다.
Target Light
Target Object
Start On
항목이 나타납니다.
Hierarchy에 있는
RoomLight
를
Target Light에 Drag합니다.
37. Target Object 연결
앞에서 만든
TargetObject
를
Target Object Slot에
Drag합니다.
이제 Button 하나가
두 Object를 동시에
제어할 수 있습니다.
38. Start On 설정
처음에는
OFF 상태로 시작해보겠습니다.
Start On
→ 체크 해제
로 설정합니다.
게임을 시작하면
RoomLight
→ OFF
TargetObject
→ Inactive
상태가 됩니다.
39. Play Mode 실행
Play Mode를 실행합니다.
Button 가까이 이동해서
Button을 바라봅니다.
Raycast가
Button의 Collider를 감지합니다.
그리고 ButtonInteractable이
IInteractable을 구현하고 있기 때문에
상호작용 대상으로 인식합니다.
40. Interaction UI 확인
정상적으로 설정했다면
화면에
[E] 버튼 누르기
가 나타납니다.
UI가 나타난다면
Raycast
IInteractable
Interaction UI
까지 정상적으로
동작하고 있다는 의미입니다.
41. E 눌러보기
Button을 바라보고
E를 누릅니다.
Input 흐름은
E
↓
Player Input
↓
Interact Action
↓
OnInteract()
↓
CurrentInteractable
↓
ButtonInteractable.Interact()
입니다.
42. OFF에서 ON으로
처음
isOn = false
상태였다면
다음 코드로
isOn = !isOn;
값이
true
가 됩니다.
43. 조명 켜기
ApplyState에서
targetLight.enabled =
isOn;
가 실행됩니다.
현재 isOn은
true이므로
RoomLight가 켜집니다.
44. GameObject도 활성화
동시에
targetObject.SetActive(
isOn
);
가 실행됩니다.
따라서
TargetObject도
활성화됩니다.
결과는
E 입력
↓
RoomLight
OFF → ON
TargetObject
OFF → ON
입니다.
45. 다시 E 누르기
같은 Button을 바라보고
E를 다시 누릅니다.
이번에는
isOn
true
↓
false
가 됩니다.
따라서
RoomLight
ON → OFF
TargetObject
ON → OFF
가 됩니다.
46. Toggle 방식
현재 Button은
누를 때마다
상태가 바뀌는
Toggle
방식입니다.
첫 번째 E
→ ON
두 번째 E
→ OFF
세 번째 E
→ ON
네 번째 E
→ OFF
를 반복합니다.
게임에서
전등 스위치처럼 사용할 수 있습니다.
47. Light만 제어하고 싶다면
Target Object는
반드시 연결할 필요가 없습니다.
Inspector에서
Target Light
→ RoomLight
Target Object
→ None
으로 두면 됩니다.
코드에서
Null을 확인하고 있기 때문에
오류 없이
Light만 제어합니다.
48. GameObject만 제어하고 싶다면
반대로
Target Light
→ None
Target Object
→ 원하는 Object
로 설정할 수도 있습니다.
이 경우
Button은
GameObject의 활성 상태만
제어합니다.
49. 둘 다 제어할 수도 있다
현재 예제처럼
Target Light
→ RoomLight
Target Object
→ TargetObject
둘 다 연결하면
하나의 Button으로
두 기능을 동시에
실행할 수 있습니다.
50. GameObject ON/OFF 활용 예
SetActive()
를 사용하면
단순한 Cube뿐 아니라
다양한 Object를 제어할 수 있습니다.
예를 들어
장식 Object
경고등 Object
벽
레이저
발판
안내 UI
효과 Object
등을
켜고 끌 수 있습니다.
51. Enemy를 SetActive할 수도 있다
예를 들어
Enemy GameObject를
처음에 비활성화해두고
Button을 누르면
활성화할 수도 있습니다.
Button E 입력
↓
Enemy SetActive(true)
↓
Enemy 등장
이런 방식으로
간단한 Event를
만들 수도 있습니다.
52. 하지만 모든 것을 SetActive로 만들 필요는 없다
중요한 점이 있습니다.
GameObject의 기능을
켜고 끄는 방법이
항상
SetActive()
여야 하는 것은 아닙니다.
예를 들어
Door라면
GameObject 자체를 없애는 것보다
문 잠금 해제
문 열기
가 더 자연스럽습니다.
앞으로 Button으로
잠긴 Door를 제어할 때는
Door Script의 Method를
호출하는 방식으로 만들겠습니다.
53. InteractionText를 상태에 따라 변경할 수도 있다
현재는 항상
[E] 버튼 누르기
가 표시됩니다.
하지만
ON / OFF 상태를
보여주고 싶다면
다음처럼 만들 수도 있습니다.
public string InteractionText
{
get
{
return isOn
? "버튼 끄기"
: "버튼 켜기";
}
}
54. 그러면 UI가 자동 변경된다
Button이 OFF라면
[E] 버튼 켜기
ON이라면
[E] 버튼 끄기
가 표시됩니다.
기존 Player UI Script를
수정할 필요는 없습니다.
55. 이번 글에서는 단순 문구 사용
이번 과정에서는
실제 물리 버튼을 누른다는 느낌을
유지하기 위해
[E] 버튼 누르기
문구를 계속 사용하겠습니다.
나중에 필요하다면
상태에 따라 변경할 수 있습니다.
56. Button Mesh도 움직이게 만들 수 있다
현재는
기능만 구현했기 때문에
E를 눌러도
Button Mesh 자체는
움직이지 않습니다.
추후에는
Button 눌림 Animation
Button Position 이동
Material 변경
버튼 소리
등을 추가하면
훨씬 자연스럽게 만들 수 있습니다.
57. 비전공자 기준으로 현재 구조 이해하기
현재 코드를
복잡하게 생각할 필요는 없습니다.
Button은 크게
세 가지 역할만 합니다.
1. 지금 ON인지 OFF인지 기억한다.
2. E를 누르면 상태를 반대로 바꾼다.
3. 그 상태를 Light와 GameObject에 적용한다.
코드로 보면
bool isOn
↓
isOn = !isOn
↓
ApplyState()
이 핵심입니다.
58. bool 다시 이해하기
bool
은
다음 두 값만 가질 수 있습니다.
true
false
이번 Button에서는
true
→ ON
false
→ OFF
로 사용했습니다.
59. ! 연산자 다시 이해하기
다음 코드에서
isOn = !isOn;
!
는 반대라는 의미입니다.
true
→ false
false
→ true
로 변경됩니다.
그래서 버튼을 누를 때마다
ON과 OFF가
바뀌는 것입니다.
60. Start On을 true로 테스트
이번에는
Play Mode를 종료하고
Button의
Start On
을 체크합니다.
Start On
→ true
상태로 게임을 실행합니다.
61. 게임 시작부터 ON
Start에서
isOn = startOn;
이 실행되므로
isOn이 true가 됩니다.
이어서
ApplyState();
가 호출됩니다.
따라서 게임 시작부터
RoomLight
→ ON
TargetObject
→ Active
상태가 됩니다.
62. 첫 E 입력에서는 OFF
이번에는
E를 처음 누르면
true
↓
false
가 됩니다.
따라서
조명과 Object가
꺼집니다.
이렇게 Inspector의
Start On을 이용해서
Scene마다
초기 상태를 다르게
설정할 수 있습니다.
63. 여러 Button에서 Script 재사용
ButtonInteractable은
여러 Button에
그대로 사용할 수 있습니다.
예를 들어
Button A
→ RoomLightA
Button B
→ RoomLightB
Button C
→ TargetObjectC
처럼 각각 다른 Object를
Inspector에 연결하면 됩니다.
Script를 새로 만들 필요가 없습니다.
64. Button A
예를 들어
Button A는
Target Light
→ HallLight
Target Object
→ None
으로 설정합니다.
그러면
복도 조명만 제어합니다.
65. Button B
Button B는
Target Light
→ None
Target Object
→ SecretObject
로 설정할 수 있습니다.
E를 누르면
SecretObject가
나타나거나 사라집니다.
66. Button C
Button C는
Target Light
→ WarningLight
Target Object
→ Enemy
로 설정할 수도 있습니다.
E를 누르면
경고등 ON
Enemy 활성화
가 동시에 일어납니다.
이런 식으로
간단한 게임 Event를
구성할 수 있습니다.
67. 하지만 현재는 하나씩만 연결 가능하다
현재 Script에는
private Light targetLight;
private GameObject targetObject;
가 하나씩만 있습니다.
따라서
Light 여러 개나
GameObject 여러 개를
한 번에 연결할 수는 없습니다.
68. 여러 Object를 제어하고 싶다면
나중에는
다음처럼
Array나 List를 사용할 수 있습니다.
[SerializeField]
private Light[] targetLights;
[SerializeField]
private GameObject[] targetObjects;
그러면
Button 하나로
여러 개를 제어할 수 있습니다.
하지만 이번 글에서는
비전공자가 기본 동작을
먼저 이해할 수 있도록
하나씩만 연결하겠습니다.
69. Button이 감지되지 않는다면
Player가 Button을 바라봐도
UI가 나오지 않는다면
먼저 Collider를 확인합니다.
Button
→ Box Collider 있음
이어야 합니다.
70. IInteractable 확인
다음으로
Button GameObject에
Button Interactable
Component가
있는지 확인합니다.
ButtonInteractable은
IInteractable
을 구현하고 있어야 합니다.
71. Ray Distance 확인
Button과 Player가
너무 멀리 떨어져 있다면
감지되지 않습니다.
이전 글의
FPSPlayerRaycast에서 설정한
Ray Distance
안쪽으로 접근해야 합니다.
예를 들어
Ray Distance = 3
이라면
대략 3 Unit 안쪽에서
상호작용할 수 있습니다.
72. Layer Mask 확인
FPSPlayerRaycast의
Raycast Layer Mask
에서
Button이 속한 Layer가
제외되어 있지 않은지 확인합니다.
테스트 단계에서는
Everything
으로 설정하면
확인하기 편합니다.
73. UI는 나오는데 Light가 안 켜진다면
[E] 버튼 누르기
가 나온다면
Raycast와
IInteractable은
정상입니다.
이 경우
Button Interactable의
Target Light
가 연결되어 있는지 확인합니다.
74. GameObject가 안 켜진다면
Target Object Slot을
확인합니다.
Hierarchy의 Object를
정확하게 연결했는지 봅니다.
그리고 GameObject가
Button 자기 자신인지도
주의합니다.
75. Button 자신을 Target Object로 넣으면 안 되는 이유
만약
Button 자신의 GameObject를
Target Object로 넣었다고 생각해보겠습니다.
Button을 한 번 누르면
SetActive(false)
가 실행될 수 있습니다.
그러면 Button 자체가
비활성화됩니다.
결과적으로
Raycast도 더 이상
Button을 찾을 수 없습니다.
따라서 Button 자신을
ON/OFF 대상으로 지정하는 것은
이번 구조에서는 피하는 것이 좋습니다.
76. Light GameObject 자체를 끄는 것과 차이
Light를 끄는 방법도
두 가지가 있습니다.
targetLight.enabled = false;
또는
targetLight.gameObject.SetActive(false);
입니다.
이번에는
Light Component의
enabled만 변경했습니다.
77. 왜 Light.enabled를 사용했을까?
Light GameObject 전체를
비활성화하지 않고
빛 기능만 끄고 싶기 때문입니다.
GameObject
→ 계속 존재
Light Component
→ OFF
상태가 됩니다.
조명 Object에
다른 Component가 있다면
그 Component는 계속 동작할 수 있습니다.
78. SetActive는 더 강한 방식
반대로
GameObject.SetActive(false)
를 사용하면
해당 GameObject 자체가
비활성화됩니다.
따라서
Renderer
Collider
Script
Child Object
등도 영향을 받을 수 있습니다.
두 방식의 차이를 기억하면 좋습니다.
79. Light 제어
이번에는
targetLight.enabled =
isOn;
으로
특정 기능만 켜고 껐습니다.
80. GameObject 제어
일반 Object에는
targetObject.SetActive(
isOn
);
을 사용했습니다.
즉
Component ON/OFF
→ enabled
GameObject 전체 ON/OFF
→ SetActive()
라고 생각하면 이해하기 쉽습니다.
81. 현재 Button 전체 흐름
현재 시스템을
한 번 정리해보겠습니다.
Player가 Button 바라봄
↓
FPS Camera Raycast
↓
Button Collider
↓
IInteractable 발견
↓
[E] 버튼 누르기
↓
E 입력
↓
ButtonInteractable.Interact()
↓
isOn = !isOn
↓
ApplyState()
↓
Light enabled 변경
+
GameObject SetActive 변경
입니다.
82. 기존 Interaction 시스템 재사용
이번 글에서 중요한 점은
Player Script를
거의 건드리지 않았다는 것입니다.
Door를 만들 때도
IInteractable
을 사용했고
Button도
IInteractable
을 사용했습니다.
Player는 항상
E
↓
Interact()
만 실행합니다.
83. Door와 Button 차이
Door는
Interact()
↓
isOpen 변경
↓
Rotation 변경
을 실행했습니다.
Button은
Interact()
↓
isOn 변경
↓
Light / GameObject 상태 변경
을 실행합니다.
같은
Interact()
이지만
Object마다
실행하는 기능이 다릅니다.
84. Interface를 사용한 이유가 보이기 시작한다
앞에서
IInteractable
을 처음 만들 때는
조금 어렵게 느껴질 수 있습니다.
하지만 이제
Door와 Button을 비교하면
왜 만들었는지 알 수 있습니다.
Door
└─ IInteractable
Button
└─ IInteractable
앞으로 Item
└─ IInteractable
모두
Player의 E 입력 시스템을
그대로 사용할 수 있습니다.
85. 다음 글에서는 Button으로 Door 제어
현재 Button은
Light와 GameObject만
켜고 끕니다.
다음 글에서는
Button을 눌렀을 때
잠겨 있던 Door를
열 수 있도록 만들어보겠습니다.
86. 다음 시스템 흐름
예를 들어
게임에서 다음과 같은
퍼즐을 만들 수 있습니다.
Locked Door
↓
직접 E를 눌러도
열리지 않음
↓
주변에서 Button 발견
↓
[E] 버튼 누르기
↓
Door 잠금 해제
↓
Door 열림
입니다.
87. Door를 SetActive(false)하면 안 된다
잠긴 Door를
Button으로 열 때
Door 자체를
SetActive(false)
해버리는 방법도 있습니다.
하지만 그러면
문이 갑자기 사라집니다.
우리가 원하는 것은
잠금 해제
+
Door Rotation
입니다.
따라서 다음 글에서는
LockedDoorInteractable
에 외부에서
잠금을 해제하거나
문을 열 수 있는 Method를
추가하겠습니다.
88. Button이 다른 Object의 기능을 호출한다
다음 글에서는
Button이 단순히
ON/OFF 상태를 바꾸는 것에서
한 단계 더 나아갑니다.
Button
↓
다른 Script의 Method 호출
↓
Door Unlock / Open
구조를 배우게 됩니다.
게임 개발에서
Object끼리 기능을 연결할 때
매우 자주 사용하는 방식입니다.
마무리
이번 글에서는
기존
IInteractable
상호작용 시스템을 이용해서
E로 사용할 수 있는
Button을 만들었습니다.
Button은
ButtonInteractable
Script를 사용하고
IInteractable
을 구현했습니다.
Player가 Button을 바라보면
[E] 버튼 누르기
UI가 나타납니다.
E를 누르면
isOn = !isOn;
으로
Button 상태를
ON과 OFF 사이에서
전환했습니다.
그리고
targetLight.enabled =
isOn;
을 이용해서
Light Component를
켜고 껐습니다.
일반 GameObject는
targetObject.SetActive(
isOn
);
을 이용해서
활성 / 비활성 상태를
변경했습니다.
전체 흐름은
Button 바라보기
↓
[E] 버튼 누르기
↓
E
↓
Interact()
↓
isOn 반전
↓
ApplyState()
↓
Light ON / OFF
+
GameObject ON / OFF
입니다.
'[ UNITY ] > - UNITY6 AI FPS 프로젝트' 카테고리의 다른 글
| Unity6 VARCO 아이템 배치하고 탄약·회복·열쇠 E입력으로 획득 및 사용하기 (0) | 2026.10.01 |
|---|---|
| Unity6 버튼으로 잠긴 문 열기 (0) | 2026.09.30 |
| Unity6 열쇠가 필요한 잠긴 문 만들기 (0) | 2026.09.30 |
| Unity6 문 Pivot 설정하고 E 입력으로 문 열고 닫기 (0) | 2026.09.30 |
| Unity6 상호작용 가능한 오브젝트 구분하고 E 상호작용 UI 표시하기 (0) | 2026.09.30 |
댓글