Unity - 반드시 고쳐야하는 코딩 방식 - 1

Youngmin Choi·2021년 12월 14일
0

Unity

목록 보기
10/16

개발하면서 고치고 개선해야할 부분이라 생각하고 작성한 내용입니다. 일기장 같은 형식으로 작성된 것이니 어디까지나 참고용으로만 봐주시고 좋은 조언이 있다면 부탁드리겠습니다^^ 편의상 본문은 평어로 서술합니다.

호출 빈도가 잦은 함수들

1. 매 프레임마다 한 번씩 호출된다.

  • Update(), FixedUpdate(), while(true) 등등

2. 빈번히 호출되는 Find(), Getcomponent()

  • 유니티에서 제공하는 Find, GetComponent 함수 자체가 가볍지 않다.
    Find 계열 함수는 인스펙터 내의 모든 오브젝트를 검사하여 해당 오브젝트를 찾는다..
    당연히 인스펙터에 객체가 많을수록 더 많은 성능을 요구할 것이다.

  • GetComponent계열의 함수는 해당하는 컴포넌트를 특정 게임오브젝트로부터 찾으려고 할 때 사용한다.
    Find보다 가벼운 편이지만, 역시나 매 프레임마다 호출하기에는 적합하지 않은 함수이다.

  • 그 외에 FindWithTag, FindObjectOfType, GetChild 등등이 있다.


    때문에 아래와 같이 고쳐쓴다!
    ex1) Start() 함수에서 처리!

    ex2) Event함수를 통해서 여러클래스 Init()함수 호출! (여러 클래스에서 Awake()Start()를 생성할 필요가 없어짐 굳굳)

3. 예외상황 처리

  • null검사 / TryGetComponent / try-catch

    try-catch문을 사용하는 경우에 유의해야 할 점이 있다.
    예외가 발생하지 않으면 try-catch는 성능을 거의 소모하지 않지만,
    예외가 발생하면 조건문과는 비교가 안될 정도로 많은 성능을 소모한다고 한다.
    따라서 예외가 자주 발생할 것 같은 코드에서는 가급적 피하자..!
    프로그래머는 '발생 가능한 모든 예외 상황'에 대응할 필요가 있다.

4. 자주 호출되는 new[]

  • 위 사진에서 보면 매 프레임마다 Update() 함수에서 new Trnasform[]를 새롭게 할당한다.
    C#은 클래스 타입 객체를 'Heap 메모리 영역'에 할당하는데, 이를 직접 할당하고 해제해줘야하는 C++과는 완전히 다르다. (C#은 할당은 자동이지만 직접적인 해제 불가능)
  • 더이상 사용되지 않는 객체를 '가비지 컬렉터(Garbage Collector, GC)'가 알아서 제거한다.
    하지만 '가비지 컬렉터'가 동작하는 동안에는 프로그램 전체가 일시적으로 정지하는 현상을 볼 수 있는데, 흔히 '렉(Lag)'이라는 현상이다. 심지어 '가비지 컬렉터'가 발생하는 타이밍도 재각각이라 예측하기가 어렵다. 따라서 매 프레임마다 배열 객체를 생성해서 '가비지 컬렉터'가 자주 동작하게 하는 것을 지양하는 것이 좋다!

5. 자주 호출되는 new()

  • 매 프레임 마다 List<>() 객체를 생성하는 경우
  • 무한 반복되는 코루틴에서 2초마다 WaitForSeconds 객체를 생성하는 경우


    공통점은 모두 클래스 타입 객체라는 것이고,
    마찬가지로 앞서 설명했듯이 가비지 컬렉터의 동작과 렉을 유발할 수 있다!


    구조체 타입은 상관 없다.
    예를 들어, 자주 쓰이는 Vector3 타입도 구조체이므로 괜찮다.


    따라서 아래와 같이 사용하자!

6. 문자열 상수에 대한 의존

  • [1]게임 오브젝트의 이름이 변경되면 대상을 찾지 못하여 null로 초기화된다. 차라리 매니저 클래스의 경우에는 싱글톤 객체로 사용하던지 아니면 FindObjectType<>을 통해 타입에 의존하는 방식을 선택하자!
  • [2]메소드의 이름이 변경되면 코루틴을 시작조차 하지 못한다. 때문에 문자열 상수 대신 nameof()를 사용하면 된다. 이를 통해 변수나 메소드, 클래스 등의 이름을 문자열 상수로 사용할 수 있다. 단, 에러 발생시 시작조차 하지 못했던 코루틴함수에 에러 컴파일을 띄우게 되기 때문에 변경된 이름이 무엇인지 확인하고 고칠 수 있게 된다.
  • [3]레이어 이름이 변경되면 -1 값으로 초기화된다. 레이어 관리를 위한 별도의 정적 클래스를 작성하는 것이 좋다. 'public const int PostPrecessLayer = 8'


    모두 특정 문자열이 변경되면 정상적으로 동작하지 않는다는 공통점이 있다. (변경에 굉장히 취약하다!)
    따라서 문자열 상수를 사용하지 않거나,
    사용하더라도 한 곳에서 사용하고 다른 곳에서는 공통 변수/상수를 참조하는 방식이 더 낫다!
profile
Always, Continually, In all circumstance

0개의 댓글