[기획/구현] 아이템 추가 - 1. 문, 히든엔딩 구현

가이등·2022년 9월 26일
0

John Lemon 프로젝트

목록 보기
8/8
post-thumbnail

⚡ 아이디어: 문(Secret, Hidden Door)

이 글에서 설명할 부분은 그림에서 노란색 부분(Rust Key - Secret Door)
파란색 부분(Hidden Key - Hidden Door) 에 대한 내용이다.

해당 내용에 대한 세부 구현 내용은 다음과 같다.

열쇠, 히든 엔딩

  • Rust Key 3개를 배치한다.
  • Rust Key 3개로 열 수 있는 문(Secret Door)을 만든다.

  • Rust Key로 열 수 있는 방 안에 Hidden Key를 배치한다.
  • Hidden Key로 열 수 있는 문(Hidden Door)을 만든다.
  • Hidden Key로 문을 열고 탈출하면 Hidden Ending을 볼 수 있다.

⚡ 문(Secret, Hidden Door) 만들기

John Lemon 프로젝트에서는 기본적으로 Level Prefab 이 제공된다.
문을 따로 조작하기 위해서 Level Prefab에 묶여 있는 문 두개를 분리시켜 다른 Prefab으로 만들어 주었다.

Secret Door
Hidden Door


이후 구현 방향은 다음과 같다.

  • 문에 트리거를 자식오브젝트로 추가한다.
  • 플레이어가 특정 조건을 충족한 상태로 트리거에 충돌하면, 문을 열겠냐는 UI가 뜬다.
  • 특정 키(Space)로 상호 작용하면 문이 열린다.


⚡ 문에 트리거 추가

빈 오브젝트를 생성한 후, 트리거를 추가하여 문의 자식 오브젝트로 넣어주었다.




⚡ 문 열 때 필요한 안내 UI 오브젝트


택스트 UI를 생성한 후, 적당한 멘트를 입력해 놓는다.
해당 UI는 특정 조건 (Rust Key 3개, 또는 Hidden Key) 을 만족했을 때만 보여야 하므로 활성화를 체크 해제해 놓는다.

또한 UI가 문 오브젝트 위에 뜨도록 간단한 스크립트를 작성하여 추가한다.


⚡ 트리거에 추가할 스크립트(OpenSecretDoor) 작성

해당 스크립트는 Secret Door의 트리거에 적용된 스크립트이다.
Hidden Door에 적용되는 스크립트 또한 거의 동일한 맥락이므로,
Secret Door의 구현 과정을 중심으로 작성해보고자 한다.

public class OpenSecretDoor : MonoBehaviour {
    public GameObject secretDoor;
    public GameObject openDoorUI;

    private void OnTriggerEnter(Collider other) {
        if (!other.CompareTag("Player") || GameManager.rustKey < 3)
            return;

        openDoorUI.SetActive(true);
    }

    private void OnTriggerStay(Collider other) {
        if (!other.CompareTag("Player") || GameManager.rustKey < 3)
            return;

        if (Input.GetKeyDown(KeyCode.Space))
            OpenDoor();
    }

    private void OpenDoor() {
        openDoorUI.SetActive(false);
        Destroy(secretDoor);
        GameManager.isSecretDoorOpened = true;
    }


    private void OnTriggerExit(Collider other) {
        if (!other.CompareTag("Player") || GameManager.rustKey < 3)
            return;

        openDoorUI.SetActive(false);
    }
}

기본적으로 콜라이더에 충돌한 오브젝트가 플레이어가 아니거나, 플레이어가 모은 rustKey가 3개가 아니면 어떠한 동작도 하지 않는다.

만약 위 두 조건이 충족될 경우, 범위 안에 들어오면(OnTriggerEnter) UI가 활성화되어 보이고,
범위 밖으로 나가면(OnTriggerExit) UI가 비활성화 된다.

조건이 충족되고 범위 내에서(OnTriggerStay) Space 키를 입력하면 문이 열린다.

문이 열리는 동작을 하는 OpenDoor() 함수에서는 문 오브젝트를 destroy해버린다.



⚡ 발생한 문제: 문 회전

문제

OpenDoor() 함수로 문을 여는 동작을 실행할 때, 문 오브젝트를 삭제하는 것보단
문 오브젝트를 회전하여 문이 열리는 것처럼 표현하는 것이 더 좋을 것 같다고 생각했다.
(이런 식으로 ..)

하지만 유니티에서 회전은 생각보다 호락호락하지 않았다.

해결 방안 탐색

해당 글에서 소개되는 방식을 참고하여 스크립트를 작성했다.

    private void Update() {
        
        if (Input.GetKeyDown(KeyCode.Space))
            startTest = true;
        
        if(startTest)
            if(transform.rotation.eulerAngles.y > -45)
                transform.RotateAround(transform.GetChild(0).position, Vector3.up, -90f * Time.deltaTime);
    }
public void RotateAround (Vector3 point, Vector3 axis, float angle);
//point를 기준점으로 axis 축에서 angle 만큼 회전한다.

테스트는 3D 큐브 오브젝트를 하나 만든 후 진행해보았다.
목표는 오브젝트의 transform.rotation.y 값을 45에서 -45로 바꾸는 것이다.

결과를 보니 원하는 곳에서 멈추지 않고 계속 돌았다.

이유를 찾아보다가 eulerAngles 에서 음수를 취급하지 않는다는 내용을 보게 되었고,
코드를 다음과 같이 수정했다.

    private void Update() {
	...
        if(startTest)
            if(transform.rotation.eulerAngles.y > 315 || transform.rotation.eulerAngles.y < 45)
                transform.RotateAround(transform.GetChild(0).position, Vector3.up, -90f * Time.deltaTime);
    }

회전을 구현하는 데에 성공했다.

이후 호기심이 생겨 다른 방식을 시도해 보았다.
rotation 값을 직접 쓰지 말고 Quaternion을 쓰면 어떨까 하는 생각이었다.

    private void Update() {
	...
        if(startTest)
            if(transform.rotation != Quaternion.Euler(0f, -45f, 0f))
                transform.RotateAround(transform.GetChild(0).position, Vector3.up, -90f * Time.deltaTime);
    }

별 생각 없었는데 잘 작동해서 놀랐다.
이런 상황같이 원하는 오일러 각이 음수일 땐 Quaternion을 사용하면 될 것 같다.

정리

이렇게 회전 자체는 구현이 완료되었는데,
이상하게 문 오브젝트는 스크립트를 적용해도 회전이 되지 않았다.

자세한 이유는 모르겠지만, 아무래도 Level 프리팹에서 Door 프리팹을 분리할 때 뭔가가 있었던 것 같다.
그렇기 때문에 어쩔 수 없이 문 오브젝트를 열 때, 오브젝트를 destroy 하도록 설정하였다.


⚡ 히든 엔딩

히든 엔딩은 Hidden Key를 얻고 Hidden Door을 열고 나가야 볼 수 있다.

복도 끝에 엔딩 트리거를 새로 만들어준다. 방식은 튜토리얼에서 소개된 내용과 같다.

Hidden Door의 오브젝트 설정과 문을 여는 동작은 Secret Door의 것과 동일하다.


⚡ 결과


히든 엔딩을 만들었다. ‡

profile
안녕하세요구르트

0개의 댓글