Prosto

유니티 프레임 확인과 고정 방법 본문

Programing/Unity 3D

유니티 프레임 확인과 고정 방법

Prosto 2016. 9. 16. 14:40

 

 

유니티를 이용하여 스마트폰  게임을 만들고 있을 때

 

간혹 프레임이 떨어지는 현상(프레임 드랍)을 목격한 적이 있었습니다.

 

게임 진행 중 한번씩 그러니 거슬리더군요.

그래서 왜 그이러는 것일까 하고

처음엔 제대로 확인하기 위하여 게임 화면에 프레임을 출력시키는 소스를 작성했습니다.

(현재 예상프레임과 최악일 때의 프레임 표시.)

 

(아래가 제가 만들어서 썼던 소스입니다.)

using UnityEngine;
using System.Collections;

 

public class FrameChecker : MonoBehaviour
{
  float deltaTime = 0.0f;

  GUIStyle style;
  Rect rect;
  float msec;
  float fps;
  float worstFps=100f;
  string text;

  void Awake()
  {
    int w = Screen.width, h = Screen.height;

    rect = new Rect(0, 0, w, h * 4 / 100);

    style = new GUIStyle();
    style.alignment = TextAnchor.UpperLeft;
    style.fontSize = h * 4 / 100;
    style.normal.textColor = Color.cyan;

    StartCoroutine ("worstReset");
  }


  IEnumerator worstReset() //코루틴으로 15초 간격으로 최저 프레임 리셋해줌.
  {
    while (true) {
      yield return new WaitForSeconds(15f);
      worstFps = 100f;
    }
  }


  void Update()
  {
    deltaTime += (Time.deltaTime - deltaTime) * 0.1f;
  }
 
  void OnGUI()//소스로 GUI 표시.
  {

    msec = deltaTime * 1000.0f;
    fps = 1.0f / deltaTime;  //초당 프레임 - 1초에

    if (fps < worstFps)  //새로운 최저 fps가 나왔다면 worstFps 바꿔줌.
      worstFps = fps;
    text = msec.ToString ("F1") + "ms (" + fps.ToString ("F1") + ") //worst : " + worstFps.ToString ("F1");
    GUI.Label(rect, text, style);
  }
} 

 

음.. 화면에 표시되는 내용은 OnGUI에 있습니다. 그 중 화면에 나타내는 부분은

    text = msec.ToString ("F1") + "ms (" + fps.ToString ("F1") + ") //worst : " + worstFps.ToString ("F1");

이 부분이죠. float 수치인 msec을 문자열로 변환하였죠.

여기서 ToString 옆에 ("F1") 부분이있죠. 이는 표시형식인데 소수 한 자리까지 표시하겠다는 얘기입니다.

그리고 ms(밀리초) fps, worst까지 같은 형식으로 사용했습니다.

 

 

이런 별도의 스크립트를 작성한 후 게임매니저나 임시 오브젝트에 달아놓고

사용한 후 나중에 불필요해지면 제거해주면 됩니다.

(이런식으로요..)

 

실행해보면 실제로 이렇게 나오는 것을 볼 수 있습니다.

(사용한 스크린샷의 예)

 

 

 

 

근데 이 프레임이 간혹 떨어지다보니

아예 고정을 시키고 싶어서 그 방법에 대하여 찾아본 적이 있었습니다.

 

그리고 사람이 눈으로 구분할 수 있는 정도와 실제 기기에서 진행되는 프레임 차이가 있기 때문에

낮아진 채로 고정시키는 것은 어떨까하고 생각했죠.

(날로 스마트폰이나 전자 기기들의 성능이 좋아져서 더욱 프레임이 잘 나오니 말이죠.)

 

그러면 모든 게임들은 프레임이 높아야만 할까요?

그렇지는 않습니다.

오히려 프레임은 35-40 정도라도 항상 안정적으로 나와야겠죠.

어떤 때는 60이 나오다가 어떤 때는 30이 나오고 이런 식으로 게임이 진행되면

플레이 하는 사람은 바로 어딘가 어색한 현상을 느끼게 됩니다.

그게 아주 짧은 순간이라면 끊김 현상(프레임 드랍)이라고 하죠.

 

사실은 프레임 고정을 하지 않아도 되지만

어느정도 안정적인 프레임을 원하여 고정하고싶을 때는 아래의 방법을 쓰시면 됩니다.

소스를 이용하여 적용시키는 방법은 아주 간단합니다.

 

Application.targetFrameRate = 40; 이 부분을 처음 게임 시작할 때 실행되는 Awake 부분.

즉 게임이 시작되는 스크립트가 있는 부분의 Awake()에 넣어주면 됩니다.

그러면 게임 시작시 프레임을 고정하여주죠.

 

그렇지만 현재는 그냥 소스만 넣어서 되지는 않습니다.

별도로 Vsync를 꺼줘야 별도로 프레임 조정이 가능합니다.

(Vsync를 사용하여 렌더링 처리를 디스플레이의 주사율과 동기화시킴으로 이미지 왜곡을 피할 수 있습니다.)

(그래픽 처리하는 동안 CPU가 주기율을 맞추느라 쉬어감 - 배터리, 발열 저하)

 

그러면 Vsync를 해제하거나 설정하는 방법을 볼까요?

유니티 상단 메뉴 중 Edit을 선택하여

Project Settings - Quality 순으로 들어갑니다.

 

그러면 우측에 Inspector 창에 Quality Settings 패널을 볼 수 있습니다.

여기서 우리는 V Sync Count 부분을 바꿔줘야 합니다.

Don't Sync로요. 여기서 만약 다시 사용한다면 Every V Blank를 선택해주세요.

 

이렇게 Don't Sync까지 선택하여줬다면

정상적으로 프레임 저하가 완료된 모습을 볼 수 있습니다.

 

(게임 실행했을 때 상단의 GUI 표시 내용)

 

이렇듯 프레임 확인을 UI로 하는 방법과 고정시키는 방법을 확인했습니다.

사실 프레임 드랍 현상이 있어 이 방법으로 해결한다면 그것은 바람직하지 않다고 봅니다.

실제로 낮은 프레임이 필요한 게임에서 사용하는 것이 적당한 사용이겠죠?

 

 

프레임 드랍 문제라면 진짜 문제점이 무엇인지 확인하고 해결하여 최상의 결과를 보여줘야겠죠?

(정말 별거 아닌 Debug.Log가 많아도 프레임 드랍 현상이 나타날 수 있고,

 obj 생성 제거가 제대로 이루어지지 않았을 수도 있고, 가비지 컬렉터가 자주 호출되어 그럴 수도 있습니다.)

이 부분은 최적화로 해결되어야 합니다.

혹은 문제점 생기면 어떤 것인지 Profiler를 통하여 확인해보고요.

 

 

다음에는 최적화와 Profiler에 대하여 다루는 글을 작성하겠습니다.

Comments