본문 바로가기
[ UNITY ]/- UNITY6 AI FPS 프로젝트

Unity6 버튼 상호작용으로 조명과 GameObject 제어하기

by MRG 2026. 9. 30.
728x90
반응형

▣ 이전 글에서는

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

입니다.

 

 

728x90
반응형

댓글