[Unity] 개발하면서 어려웠던 점

ChangBeom·2024년 6월 28일
0

Unity

목록 보기
1/8

[개요]

7월 유니티 챌린지 나 혼자만 레벨 업: Unity로 갓생살기의 사전 미션으로 unity 개발을 하면서 겪었던 어려움과 그 극복 과정을 작성하며 되새기는 과제이다.

[주제]

  1. Wheel Collider를 활용한 자동차 구현 : unity에서 지원하는 wheel collider를 이용해 바퀴를 구현하는데 있어서 겪었던 마찰력과 미끄러짐에 관한 내용
  2. 포톤을 이용한 네트워크 동기화 : 포톤을 이용해서 멀티플레이 게임을 만들 때 사용할 수 있는 여러가지 동기화 방법
  3. 일시정지 상황에서의 coroutine : timeScale이 0일 때 coroutine 사용법

[Wheel Collider를 활용한 자동차 구현]

유니티를 활용해서 레이싱 게임을 만들 때, wheel collider를 사용해서 바퀴를 구현했다. 처음엔 다른 설정 값은 변경하지 않고 단순하게 바퀴에 Toque(회전력)값만 줘서 잘 굴러가는지만 확인하고 사용했다.

문제는 레벨디자인을 하며 생겼다. 레벨디자인을 하며 난이도를 조정하기 위해 Toque의 최대값을 올렸는데, 속도가 생각처럼 오르지 않고 차량이 계속 미끄러졌다.

이 문제를 해결하기 위해 마찰력과 미끄러짐 정도를 제어하는 것에 대해 공부를 하게 되었다.

참고 : https://micropilot.tistory.com/2663


세로축 : 마찰력
가로축 : 미끄러짐


위 그래프를 보면 바퀴의 속도가 증가하면 마찰력도 같이 증가한다. 속도가 일정 수준까지 올라가면 마찰력은 떨어지고 미끄러짐 정도만 늘어나는 지점이 있는데 그 점을 Extremum 이라고 한다. 계속해서 속도가 증가하면 마찰력은 유지되고 미끄러짐 정도만 늘어나는 지점이 있는데 그 점을 Asympote 라고 한다. 이 점을 활용해서 wheel collider 컴포넌트에서 마찰력과 미끄러짐 정도를 잘 조정해야 속도를 올려도 차량이 미끄러지지 않는다.

위 사진을 보면 알 수 있듯이 Extremum값과 Asymptote값을 변경할 수 있는데, 일반적으로 Stiffness를 변경해서 마찰력을 변경한다. Stiffness의 default값은 1이며 1이면 설정된 그대로의 값이 적용된다. 1보다 작으면 그 비율만큼 마찰력이 작아지며 0이되면 마찰력이 없는 상태가 된다.

[포톤을 이용한 네트워크 동기화]

PUN2(Photon Unity Networking2)는 유니티용으로 제작된 포톤 네트워크 엔진이다. 유니티의 에셋스토어에서 임포트해서 간편하게 사용할 수 있다.

PUN2에서 동기화 방법은 총 3가지이다.

1. Photon View : 갱신이 빈번한 경우

PUN2에서 지원하는 네트워크 동기화용 컴포넌트이다. 네트워크를 통해 동기화될 게임 오브젝트에 Photon View 컴포넌트를 추가하면 로컬과 리모트를 구별할 수 있게 된다. Photon View를 통해 View ID를 부여해주면 다른 클라이언트에서도 같은 오브젝트로 판단하여 동기화가 된다.

2. RPC : 갱신이 드문 경우

RPC란 Remote Procedure Call의 약자로 로컬과 리모트에 동일한 코드가 존재할 때 리모트의 코드를 실행하는 것이다.
매우 빠른 물체를 동기화할 때 Photon View를 이용해서 Transform을 동기화 시키면 끊기면서 이동하는 현상이 생길 수 있기 때문에 위치를 동기화 시키는 것이 아니라 리모트에서 로컬과 동일한 코드를 실행하여 동기화 시키는 방식이다.

3. Custom Properties : 갱신이 아주 드문 경우

키-값 형태로 이루어진 HashTable이다. 쉽게 말하면 변수를 동기화 시켜주는 방식이다. 게임 내에서 자주 변하지 않는 변수를 동기화할 때 사용한다.

  • 개인적인 생각이지만 Photon View나 RPC보다 사용빈도가 낮은 것 같다.

[일시정지 상황에서의 coroutine]

유니티 개발을 하다보면 Invoke나 Coroutine을 사용해서 몇 초 뒤에 코드를 실행 시키는 경우가 많다.

유니티를 접한지 얼마 안됐을 때, 일시정지(timeScale이 0일 때) 상황에서 Invoke를 사용했는데 아무리 시간이 지나도 코드가 실행되지 않았다. 그 당시 내가 구현하고 싶었던 것은 ESC를 누르면 일시정지가 되며 메뉴창이 나옴 -> 메뉴창에서 메인메뉴로 버튼을 누름 -> 클릭 효과음이 나오면서 1초뒤에 메인메뉴로 이동 이였다. 이 당시 나는 Invoke가 timeScale이 0일 때 실행되지 않는 것을 모르고 많이 헤맸었다.

그렇게 알게된 점은
1. Invoke는 timeScale이 0일 때 사용할 수 없다.
2. Coroutine은 Invoke와 비슷한 용도로 사용할 수 있다.
3. Coroutine은 일반적으로 yield return new WaitForSeconds(1f) 같이 사용하는데, yield return new WaitForSecondsRealtime(1f) 같이 사용하면 timeScale이 0인 상황에서도 코드의 실행을 지연시킬수 있다.

  • Invoke는 간단해서 사용하기 편하고, Coroutine은 활용성이 더 높은 것 같다. 상황에 따라 적절하게 사용하자!

0개의 댓글