Unity

[Unity] 코드: 안티데시스 보스전 리빌드하기 / 5주차

시카Dev 2025. 6. 16. 12:49

2025. 6. 5 <싱글톤 패턴으로 NPC의 대사를 구현해보자>

플레이어가 NPC와 상호작용을 할 때 대사창이 보여지는 것을 구현할 것이다

우선 NPC 오브젝트 하위에 대사창이 보여질 canvas와 설명문구를 넣는다

canvas는 world space 기준으로 설정한다

 

처음엔 안보였으나 UI 깎기를 수차례 시도한 후에 보여졌다

이제 여기에 이전에 사용했던 대사 스크립트를 적용할 것이다

 

흠... 그런데 대사 스크립트를 재사용하려고 보니 필요없이 참고된 것이 많다. 가령 bossHealth와 startGame 변수는 사용하지 않을 것이다.

그렇다면 NPC대사를 위해 이 스크립트를 새로 작성하고 어느 정도 가공해야 할까? 하지만 NPC 대사 뿐만 아니라 추후 구현할 플레이어의 대사에도 이런 방식으로 구현해야 할까?

 

모든 대사 기능은 diaglogues 배열에 저장된 대사를 한줄씩 줄력하고, 다각다각 한 글자씩+효과음이 출력된다. 상황에 따라 특정 게임 오브젝트가 꺼지거나 켜지는 경우가 있을 뿐이다.

 

때문에 이것은 싱글톤 패턴을 사용하면 좋을 것 같다. 공통적인 기능은 묶고, 필요할 때마다 인스턴스로 호출하면 좋겠다

싱글톤 패턴이란 프로젝트 내에서 단 하나만 존재하는 전역 인스턴스를 만드는 패턴이다.

 

싱글턴 패턴 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전.

ko.wikipedia.org

 

이렇게 해서 여태 4가지의 디자인 패턴을 적용해본 것 같다.

전략 패턴, 옵저버 패턴, 오브젝트 풀링, 싱글톤 패턴...

 

여튼 DiaglogueManager 스크립트를 만들어 정적으로 인스턴스화 했다

Awake에서 인스턴스가 없으면 본인으로 세팅하고, 있다면 중복을 방지하기 위해 본인을 Destroy한다.

 

이후 함수에서는 이전에 작성했던 대사 스크립트를 재활용했다.

차이점이 있다면 매 대사마다 원본 게임처럼 마우스 입력을 기다린다

 

하지만 위에서 TMP_Text를 공용으로 입력받으면 다양한 곳에 활용할 수가 없다.

따라서 이것을 파라미터로 받도록 수정해야한다

 

요로코롬 적용하면 NPC의 말풍선을 적용할 수 있다

 


 

2025. 6. 6

코테+알바로 제작 진도 휴식!

 


 

2025. 6. 7 <주인공의 대사를 추가하자>

원본 게임 초반부에는 주인공의 대사가 출력된다

보스전이 시작되고 플레이어가 잡몹을 때릴 때 NPC에게 도움을 요청하지 않으면 데미지가 들어가지 않아 '동료에게 다가가서 말을 걸자!' 식으로 힌트 문구를 던지기 때문이다

 

이 또한 그저깨 구현했던 싱글톤 대사 스크립트를 재활용할 것이다.

 

플레이어 오브젝트에 동일하게 world space canvas를 추가하고, 대사창과 대사가 작성될 TMP를 넣는다

 

PlayerDialogue 스크립트에는 출력할 대사를 적는다.

팁이 있다면 \n으로 줄구분을 하며 +로 두 문장을 이어주면 된다

 

이제 이것을 NPC에게 말 걸기 전 잡몹과 보스를 공격할 때 출력하면 된다.

그렇다면 어디 오브젝트에 달아주면 좋을까? 플레이어 오브젝트? 잡몹 오브젝트? 보스 오브젝트?

내 생각엔 무기 오브젝트에 달아주면 좋을 것 같다. 무기의 콜라이더가 잡몹 콜라이더에 닿을 때 힌트를 던져주면 좋을 것 같기 때문이다

 

무기 오브젝트에서 NPC의 도움을 받지 않고 잡몹을 공격하려 할때(=canbeDamaged가 false일때) 플레이어의 대사창이 나타나게 했다

 

요로코롬 도움을 받기 전에 잡몹을 공격하려 하면 대사가 잘 출력되는 것을 확인할 수 있다

 


 

2025. 6. 8 <보스에게 공격받게 해보자>

보스와 잡몹의 구현을 얼추 했겠다 일정 거리 내에 플레이어가 있다면 데미지를 받게 해야한다

 

보스의 패턴은 다음과 같다

1. 플레이어가 보스의 사정거리 내 들어온다

2. 보스가 돌진하여 플레이어를 뚫고 간다

3. 플레이어는 체력이 -1되고 보스는 약 2초 동안 휴식한다

AttackPlayer() 함수와 Attack 코루틴을 작성한다

어택 플레이어는 현재 보스와 플레이어의 거리를 측정한 뒤 특정 범위 내에 들어갔다면 공격 코루틴을 실시한다

 

왜 콜라이더를 사용하지 않고 실시간으로 플레이어와의 거리를 계산했을까??

1. 보스의 범위를 콜라이더로 한다면 콜라이더가 닿을 때마다 연산이 일어나므로 추가적인 처리를 해야한다

2. 사정거리를 변경한다면 콜라이더도 일일히 수정해야 한다

3. 거리 계산은 직관적이고 조건부로 공격 패턴을 넣기에 좋다

 

언제나 코드를 작성하기 전에 왜 이렇게 설계했는지 그 이유를 찾아보는 습관이 중요하다.

 

이때 돌진은 플레이어의 위치로 향하고, 돌진한 궤적 주변에(?) 플레이어가 있다면 데미지를 입게 된다.

didDamage로 플래그를 설정한 것은 중복 데미지가 들어가는 것을 방지한다.

 

요로코롬 잘 데미지를 입는 것을 볼 수 있다

 


 

2025. 6. 9 <잡몹에게 공격받게 해보자>

어제 구현했던 돌진 코드를 잡몹에게도 적용할 것이다

잡몹의 돌진이 보스의 것과 차이점이 있다면 속도가 더 느리고, 돌진 궤적 또한 짧다

 

차이점이 있다면 인스턴스로 나오는 잡몹들은 프리팹을 활용한 것이기에 playerHealth를 대입한 것이 null이 된다.

따라서 이것은 public PlayerHealth playerHealth;으로 먼저 선언하고, playerHealth = FindObjectOfType<PlayerHealth>();으로 참조를 해야한다

 

말썽의 대부분은 컴포넌트에서 오브젝트를 참조하는 것이 제대로 끼어져 있지 않아서 그렇다... 이를 잘 확인해야한다!

 


 

2025. 6. 10 <대사가 나올 때는 멈춰보자>

원작 게임에서는 NPC와의 대화 상호작용을 할때 플레이어를 향해 움직이면 잡몹들이 잠시 멈춘다. 이를 유니티에서도 구현해보려고 한다

 

원본 DialogueManager 스크립트에서 isTyping bool타입 변수를 선언했다

대사가 출력되는 동안 true고 전부 출력 시 false가 되도록 하였다

또한 잡몹 스크립트에서 잡몹이 isTyping false일때만 움직이도록 하였다

 

이렇게 NPC에게 말을 걸때 잡몹이 멈추고, 대화가 모두 끝나면 움직이게 된다

 

또한 대화가 끝난 후 타이머가 실행되도록 수정했다!