Unity

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

시카Dev 2025. 5. 15. 14:31

 

CS 공부와 면접 스터디 및 코테로 취준 생활을 보내다가 유니티로 포폴을 하나 더 만들면 좋을 것 같다는 생각이 들었다.

 

포폴 주제를 많이 고민해보며 모작 쪽으로 방향이 잡히다가... 언뜻 내가 만들었던 게임을 유니티로 리빌드해보면 어떨까?! 싶었다.

 

 

코드: 안티데시스 Demo on Steam

An irreversible choice between brothers, endless pursuit, and hidden truths. What awaits at the end...?

store.steampowered.com

(이 게임 맞다 으흐흐, 홍보 겸 링크를 올려보았다)

 

 

코드 안티데시스는 RPG Maker, 유니티나 언리얼과 다르게 비주류 엔진으로 만든 것이라 일종의 사이드 프로젝트가 되었다.

게임 후반부 보스전이 테스터분들에게 괜찮은 평가를 받았던 것으로 기억하는데, 이것을 유니티로 한번 제작해보면 어떨까? 그리고 RPG Maker 엔진 한계상 넣지 못했던 패링, 구르기, 추가 보스 패턴, 카메라 연출 같은 요소도 추가해보면 어떨까? 

 

요점은 사이드 프로젝트를 유니티로 그대로 옮기는 것이 아니라, 기존의 핵심 구간을 리메이크한 기술을 시연해보는 것이다. 이론으로만 공부했던 최적화 기법, 유니티 기능 등을 적용하고 실습하는 목적도 있다. 작은 프로젝트부터 하나씩 적용해보기!

 

이는 기존의 리소스와 기획을 다시 활용할 수 있기에 시간적인 측면에서 장점도 있는 듯 하다. 따라서 시간을 아끼면서 카메라 연출 및 효과에도 집중하여 좀 더 완성도 있는 플레이를 제작하고 싶다.

 

다만 3D 포폴만 하다가 2D 포폴을 해도 되는지... 고민 끝에 현직자 선배님께 여쭤봤는데 문제는 없어보인다고 하셨다. 오히려 좋을수도 있다고 하셔서 자신감을 가지고 포폴을 제작해보기로 한다..!

 

 

이전에 게임을 제작할때 각 주마다 일지를 남겼던 것을 바탕으로, 이번 개발에도 각 주마다 일지를 작성하려고 한다.

Unity 2D는 처음이라 분명 시행착오가 많이 생길 것이다. 하핫

 


 

2025. 5. 7 <맵타일을 만들자>

해당 보스전 후반부에 사용했던 리소스를 활용하는데, 유니티는 알피지 메이커와 다르게 타일셋을 따로 지정해줘야 하는 것으로 알고 있다. (알피지 메이커는 규격에 맞게 도트만 찍어놓으면 알아서 import가 된다)

 

 

 

[Unity3D] Tilemap (1) - 2D 게임의 기본 타일맵!

Tilemap (1) - 2D 게임의 기본 타일맵! 작성 기준 버전 :: 2019.1 - 2019.2 [이 포스트의 내용은 유튜브에서 영상으로도 시청하실 수 있습니다] 예전에 RPG메이커를 사용했을 때는 맵이 타일(Tile) 방식으로

wergia.tistory.com

 

해당 강의를 통해 먼저 배경을 그릴 타일맵을 지정했다. RPG Maker에서는 가로로 35 세로로 25칸이었으니 유니티에서도 동일하게 잘라주면 수많은 타일셋 조각이 나온다

 

 

음? 근데 자른 맵타일이 화면에서는 깍두기마냥 꽉차지 않고 작게 나오는 것이 아닌가?

 

 

 

From the unity community on Reddit: Why is my tilemap smaller than my grid? how do I fix this?

Explore this post and more from the unity community

www.reddit.com

해결책은 참 간단했다. 레딧에서 어느 선생님이 친절히 알려주셨다

 

 

스프라이트의 해상도에 맞게끔 인스펙터 창에서 Pixels Per Unit을 알맞게 지정하면 되었다.

나의 경우는 알만툴에서 사용했던 해상도대로 48을 입력하니 해결되었다

 

 

짜잔~~ 이렇게 하면 맵이 만들어진다.

 

왜 굳이 타일맵으로 맵을 만들었을까? 라는 질문에는...

추후 타일맵에 콜라이더를 추가하여 보스전에서 어떠한 상호작용을 하기 위해서라고 생각한다. (ex. 플레이어가 벽에 부딪혔을 때 데미지를 입는다던가)

 

 

위와 같은 방법으로 스프라이터 에디터 - Slice - Gride by Cell Size - Pixel Size 48로 Apply하여 나눠준다

 

이런식으로 부드럽게 움직이는 것을 확인할 수 있다.

유니티가 어느 면에서는 편한게, 대각선 이동을 당연하게 제공해준다..ㅋㅋㅋ

이제 플레이어가 각 방향에 움직일 때마다 나오는 걷기 애니메이션을 만들어야 한다

 


 

 

2025. 5. 9 <애니메이션을 만들자>

어제와 오늘은 알바하느라 피곤하지만 진도는 나가야 한다

 

애니메이션과 애니메이터로 블렌더 트리를 만들고 각 애니메이션을 연결했다.

 

그리고 내가 기대했던 것...

우 방향키를 누르면 우로 이동하고 우측을 바라보며 끝나겠지? RPG Maker에서 그랬던 것처럼?

 

 

그만 알아보자(ㅋㅋㅋ) 트리가 한바퀴 돌게 되었다

아무래도 조건문 제어를 좀 더 추가해야겠다. 블렌더 트리 형태도 수정해야겠다.

 

 

한편 Has Exit Time에 따른 애니메이션 변화를 체감해보고 있다.

이 옵션을 키면 아주 작게 움직이더라도 애니메이션이 모두 재생된 후 다른 상태로 변하는 것을 볼 수가 있는데, 나중에 플레이어가 찔끔찔끔(?) 움직이는 것에 따라 자연스럽게 걷기 애니를 출력한다면 옵션을 끄는 것이 좋은 것 같다.

 

 

이렇게 해서 RPG Maker에서 기본으로 제공했던 캐릭터의 이동을 블랜더 트리로 구현해보았다

바라보는 방향을 Looking int 변수로, 현재 걷는지는 Running bool 변수로 제어했다

아직 고쳐야 할 점은 이동 중에 다른 키를 누르면 그 방향으로 얼굴을 돌리지 않고 여전히 터벅터벅 걷는 점이 있다

 

추가적으로 shift를 누르면 날아다니는 모션 추가도 필요하다

 


 

 

2025. 5. 10 <애니메이션을 만들자2>

플레이어가 시프트 키를 누르면 나는 애니메이션을 추가했다.

하지만 여전히 키가 씹히고 버벅이는 현상이 있었다. 따라서 플레이어의 움직임을 제어하는 코드를 보니...

 

// Manage the Player Movement
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");

Vector3 movement = new Vector3(horizontal, vertical, 0);
transform.transform.Translate(movement * moveSpeed * Time.deltaTime, Space.World);

아마 GetAxis의 문제가 아닐까 하였다.

 

 

유니티 :: GetAxis와 GetAxisRaw

1. Input.GetAxis(string name)-1.0f 부터 1.0f 까지의 범위의 값을 반환한다. 즉, 부드러운 이동이 필요한 경우에 사용된다. 2. Input.GetAxisRaw(string name)-1, 0, 1 세 가지 값 중 하나가 반환된다. 키보드 값을 눌

onecoke.tistory.com

GetAxis는 -1~1까지의 값을 float 값으로 부드럽게 반환한다.

한편 GetAixRaw는 -1, 0, 1의 값을 반환한다. 나의 경우에는 GetAixRaw가 프로젝트에 맞는 것 같아 그렇게 수정하였다

 

 

수정 후 애니메이션이 정상적으로 출력되는 것을 확인할 수 있었다

걷기 4종+바라보기 4종+날기 4종 애니메이션 때문에 트랜지션이 자칫 복잡해질 수 있어서 꼼꼼히 확인하는 것이 좋겠다.

그런데 지금보니 그림자가 없으니까 조금 어색해 보인다..ㅋㅋㅋ

 


 

 

2025. 5. 11 <애니메이션을 만들자3>

 

각 캐릭터 하단에 그림자를 추가하고, 보스몹의 나는 애니메이션도 제작했다.

 

이후 무기 구현은 전략 패턴을 활용하여 구현해볼 예정이다.

또한 플레이어와 보스의 체력바는 옵저버 패턴을 활용할 것이다

작은 프로젝라도 내가 공부해본 디자인 패턴과 최적화 기법을 적용하고 싶다.

 


 

2025. 5. 12 <전략 패턴을 구현해보자>

 

 

[디자인패턴] 전략 패턴 ( Strategy Pattern )

전략 패턴 ( Strategy Pattern )객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여,객체의 행위를 동적으로 바꾸고 싶은 경우 직접

victorydntmd.tistory.com

전략 패턴이란 각 객체를 정의하고 그것을 묶고 관리하는 인터페이스를 만든 뒤 클라이언트에서 요청사항이 오면 객체를 바꿔주는 디자인 패턴이다.

가령 FPS 장르에는 다양한 무기가 있고 각 무기에 따라 데미지, 애니메이션 등이 관리되고 있다

하지만 각 무기에 대해 if로 일일히 관리하지 않고 통째로 묶어서 무기를 관리한다.

 

플레이어가 주기를 줍거나 교체함(=클라이언트 요청) → WeaponManager에서 이를 요청함(=Context) → 인터페이스로 구현된 IWeapon에서 상속받은 무기로 전달됨

 

이런 식으로 작동된다고 보면 될 것 같다.

 

우선적으로 간단히 무기에 대한 정보를 추상인터페이스로 선언하고 IWeapon이라 지었다.

이하는 플레이어가 사용할 근접 무기와 원거리 무기 두 가지를 작성했다

 

보통 예제를 보면 무기가 세 개 이상일 때부터 이 패턴을 적용하던데, 나는 공부해본 디자인 패턴을 실습하는 것이 프로젝트의 목적이므로 적용할 수 있으면 하려고 한다.

A키와 S키를 눌러 교체하려고 했는데, 생각해보니 무기가 두개라 tab키로 스와핑 하는 것이 편해보여 주석처리했다.

 

무기를 관리하는 WeaponManager에서는 사용하는 무기를 관리하고 이를 교체할 수 있게 한다.

 

마지막으로 PlayerController 스크립트에 WeaponInput 함수를 넣고 실행했다.

 

<내가 원하는 것>

1. RPG Maker 때처럼 Z키로 공격하기

2. tab키를 누르면 무기 스와핑하기

 

는... 정작 무기가 교체되지 않는 기묘한 현상을 볼 수 있었다

 

왜 그랬을까?? 아마 ChangeWeapon 메서드가 제대로 작동하지 않았을까??

바꾼 무기가 갱신이 되지 않은걸까?

그래서 foreach문과 다른 방법을 써보았다. 한참 헤매다가 이 방법으로 다시 잘 작동되었다

 

먼저 서두에 weapon_index를 0으로 선언한다.

이는 교체할 무기의 인덱스 번호며 처음에는 Baton으로 무기가 고정된다.

 

이후 ChangeWeapon에서 현재 인덱스 번호를 +1한뒤 무기 배열 길이로 나눈다. 이 값을 현재 무기의 인덱스로 지정한다.

ex) 현재 weapon_index가 0이면 1로 증가되고 2로 나눈 나머지가 1이 된다. 따라서 첫번째 무기에서 두번째 무기로 교체된다.

 

처음에는 저 주석처리된 if else문으로 구분했으나 만약 무기 갯수가 늘어난다면 추가로 지정해야 하므로 무기 배열 길이로 나눠주는 것이 더 효율적이라 생각하여 사용하게 되었다.

 

이렇게 해서 전략 패턴을 적용해 무기 교체를 구현해보았다

 


 

2025. 5. 13 <무기를 휘둘러보자>

 

IWeapon의 Baton 클래스를 분리하고, 쿼터니온을 통해 코루틴으로 애니메이션을 만들고, 게임 오브젝트 배열로 WeaponManger에서 무기를 입력받는 것을 구현했다. 

중간에 Object reference not set to an instance of an object 오류를 해결하느라 하나씩 콘솔창 코드를 넣어보며 어디서 틀린건지 확인하느라 2~3시간은 걸렸다... (대충 뺑이치기를 했다는 내용)

 

진압봉이 휘둘러지는 각도와 위치를 깎으면 이렇게 된다.

 

처음에 오른쪽 방향만 원하는 각도로 휘둘러지지 않는 이상한 점이 있었다. 난 100도 ~ 20도로 회전하길 원했는데 이상하게 -180도 혹은 180도로 고정되어있는 것이 아닌가..?!

이는 오른쪽 방향의 애니메이션 각도를 계산할 때 다른 방향과 다르게 혼자서 수를 빼야하기 때문인 것으로 생각한다.

 

무기가 휘둘러지는 Rotation Z 값은 아래의 각도로 조정하고 있다.

-100 ~ 20 <- 아래일때

-180 ~ -100 <- 왼쪽일때

100 ~ 180 <- 위쪽일때

100 ~ 20 <- 오른쪽일때

 

근데 다른 각도는 전부 80을 더하는데 오른쪽만 80을 빼고 있지 않는가?!

 

따라서 if문으로 오른쪽만 볼 때를 지정하여 쿼터니온을 따로 두었다. 

앞으로는 오른쪽일때만 시작되는 회전값과 끝나는 회전값이 끝나고, 나머지 방향은 80씩 더해가며 종료된다.

코루틴 회전 애니메이션은 채찍피티 선생님의 도움을 받았다

 

또한 코파일럿 선생님의 말씀을 잊지 말자. 쿼터니온을 오일러 각도로 변환할 때, Unity는 -180~180도 범위로 자동 변환한다는 것도 잊지 말자.

 


 

 

2025. 5. 14 <벽을 막자>

 

 

각 벽에 2D 콜라이더를 추가하고, 플레이어에도 콜라이더와 강체를 추가했다

또한 플레이어의 이동 코드에 리지드바디도 transform하여 같이 이동하도록 하였다.

 

아스톨포도 추가하고~~