// 일반 //
프로파일을 먼저 하세요. 병목 지점이 확실하지 않다면 코드를 개선하거나 텍스쳐 사이즈를 줄이는데
시간 낭비하지 마세요. 항상 당신의 게임을 프로파일해서 병목 지점을 찾아내세요.
애플의 샤크는 OpenGL기반 응용프로그램을 위한 좋은 프로파일링 툴입니다.
프로파일을 다시 하세요. 최적화한 후 다시 프로파일하는 것을 잊지 마세요. 이런 과정 속에서 추가적인 병목지점을 찾아낼 수도 있습니다.
작업이 먼저 성능은 나중. 당신의 게임을 순조롭게 만들어가는데 시간을 투자하세요.
빠르게 변경과 업데이트를 할 수 있다면 추후에 성능 작업도 쉬워집니다.
Scene View 안에 scene을 테스트 하세요. scene내에 일반적인 오브젝트나 스크립트가 부착된 오브젝트로 인해 성능상 느려지는 것을 확인할 수 있습니다. Scene View가 느릿느릿하다면 지오메트리나 텍스쳐를 최적해보고 만약 아니라면 스크립트나 물리가 병목 지점일 가능성이 높습니다.
각각의 게임 오브젝트들을 중지시켜보세요. 플레이 모드상에서 각각의 게임 오브젝트들을 번갈아가면서 활성화/비활성화 시켜보세요. 느려지게 만드는 부분이 어디인지 범위를 좁혀볼 수 있습니다.
// 메쉬 //
가능하다면 근처의 오브젝트들을 합쳐서 하나의 재질을 가진 하나의 오브젝트로 만드세요.
예를 들면, 레벨상에 하나의 테이블이 있고 테이블 위에 몇 가지 오브젝트가 있다면 하나로 합치는 것이 좋을 수 있습니다. (이것은 여러 텍스쳐를 하나의 커다란 텍스쳐 아틀라스로 합치는 작업이 필요할 수 있습니다.)
유니티가 렌더링할 오브젝트 수를 줄이는 것은 성능 상에 큰 이점이 될 수 있습니다.
불필요한 메쉬를 가지고 있지 마세요. 게임 내 캐릭터가 있다면 하나의 메쉬인 것이 좋습니다.
배가 있다면 하나의 메쉬로 이루어진 것이 좋습니다. 유니티가 렌더링하는 각각의 메쉬마다 심각한 오버헤드가 생깁니다.
하나의 메쉬당 하나의 재질. 분리된 개별 메쉬를 렌더링 하는 것처럼 렌더링할 재질별로 구분해서 다루세요.
최소화된 극단적인 로우 폴리곤 메쉬들로 성능을 올릴 수 있습니다.
다만 하드웨어 변환 및 조명이 가능한 주요 그래픽 카드는 초당 엄청난 양의 폴리곤을 처리할 수 있고
메쉬를 렌더링하는 그래픽 카드의 오버헤드는 충분히 감수할만 하다는 의미입니다.
폴리곤 수를 지나치게 절약하는 것은 게임을 각져 보이게 만들기만 하는 일 일지도 모릅니다.
캐릭터를 1500-2000 개 정도의 삼각형으로 만드세요. 이 수는 좀 극단적일 수 있지만 아티스트가 시작하는 시점에서 질과 성능 상에서 조율하기 좋은 지점을 제공할 수 있습니다.
비고. 만약 모델이 사각형으로 이루어졌다면 유니티는 사각형을 두 개의 삼각형으로 변환해서 읽어들일 것 입니다.
// 조명 //
픽셀 조명은 게임을 보기 좋게 만들지만 지나치게 낭비하진 않도록 하는 것이 좋습니다.
그러나 품질 매니저를 사용하는 것은 각각의 품질 레벨에 따른 픽셀 조명 수를 조절하고 완성된 게임에서 성능과 품질 사이에서 타협할 수 있는 방법을 제공하는 좋은 방법입니다.
스팟 조명은 포인트 조명보다 비용이 비싸고 이 둘은 전역 조명보다 비쌉니다.
장면 내의 조명 연출을 위한 좋은 방법은 가장 먼저 원하는 조명을 연출하는 겁니다.
그 다음 조명들을 살펴보면서 어떤 조명이 중요한지 분류하고 장면을 최대한 유지하면서 줄일 수 있는 조명들을 줄여나가는 겁니다.
포인트 조명과 스팟 조명은 오직 조명 범위 내의 메쉬들에게만 영향을 줍니다.
만약 감쇄도가 적용된 포인트, 스팟 조명의 범위를 벗어났다면 메쉬는 더이상 조명의 영향을 받지 않고 성능을 아낄 수 있습니다. 이러한 점은 포인트 조명의 범위가 작을수록 범위 안에 들어오는 오브젝트 수가 적어질 수 밖에 없기 때문에 더 큰 성능상 혜택을 줄 수 있다는 것을 의미하기도 합니다.
기억해두실 점은 하나의 메쉬는 가장 밝은 8개의 조명에만 반응 한다는 점 입니다.
// 텍스쳐 //
보기 좋은 상태가 유지되는 한 텍스쳐 사이즈는 최대한 작게 줄이세요.
그래픽 카드가 한번에 모든 텍스쳐를 그래픽 메모리에 담지 못한다면 규칙적으로 시스템 메모리와 그래픽 메모리 사이를 옮겨다니게 될 것 입니다. 최신 컴퓨터로 충분한 대역폭을 제공받는다면 이건 문제가 되지 않습니다. (다만 적은 그래픽 메모리는 컴퓨터를 극단적인 상황으로 내몰 수 있습니다.) 굳이 이미지 에디터로 텍스쳐 사이즈를 변경할 필요도 없습니다.
개별적인 이미지 설정을 통해 사이즈를 수정해서 유니티에서 읽어들이도록 할 수 있습니다.
낮은 품질의 이미지 파일들을 사용하지 마세요. 낮은 품질 또는 적은 컬러의 jpeg, png, gif 파일 사용의 결과를 보장할 수 없습니다. 유니티는 자동으로 출하 과정에서 모든 텍스쳐를 압축합니다. 그러므로 원본의 고 해상도 파일 상태를 유지하세요. 압축과 해제를 반복하는 과정에서 생각했던 것 이상으로 품질이 떨어질 수 있습니다.
// 사운드 //
압축된 ogg 파일을 사용하세요. 다른 오디오 포맷은 압축되지 않은 PCM 오디오 상태로 저장될 수 있습니다.
작은 사운드 효과들은 압축되지 않은 오디오로 사용하세요. 유니티는 모든 ogg파일을 압축해제 합니다. 압축해제 후 wav나 aiff파일로 저장해두기 위해 비용이 발생하지만 압축되지 않은 오디오 파일은 불필요한 CPU 사이클을 소모하지 않습니다. 앞에서 얘기한 작은 사운드 효과는 사격 소음, 발 소리 등을 말합니다.
// 물리 //
각각의 강체들은 연산이 필요하므로 적을수록 좋습니다.
강체들은 또한 각도나 이동량이 한계점 이하로 떨어지면 작동을 중지하게 됩니다.
이때 다른 힘을 받거나 충돌이 일어나지 않는 한은 요구되는 연산량이 대폭 줄어들게 됩니다.
복잡한 충돌체크는 간단한 것보다 더 많은 연산을 필요로 합니다.
다수의 구형 충돌 메쉬들을 가지고 있는 커다란 더미의 강체들은 지형 위에서 서로 멀찌감치 떨어져 있는 구형 충돌 메쉬보다 처리하기가 더 복잡할 수 있습니다.
// 셰이더 //
간단한 것과 비교했을 때 복잡해질수록 성능상 비용이 커집니다.
정점 단위의 셰이더는 텍스쳐를 입히거나 라이팅을 적용하는데 있어서 가장 빠를 수 있습니다.
장면내 픽셀 조명이 없거나 품질 매니저에서 모든 픽셀 조명을 끌 경우 대부분의 셰이더는 좀더 간단한 정점 단위의 셰이더로 후퇴하게 될 것 입니다.
// 스크립트 //
올바른 알고리즘을 사용하고 있습니까? 올바른 알고리즘을 선택하는 것은 코드를 최적화하는 다른 어떤 작업보다도 더나은 결과를 이끌어 낼 수 있습니다. 작은 자료구조에서 복잡한 초기화 과정이 필요한 것보다 적은 설정의 느린 알고리즘을 사용하는 것이 현명할 때도 있습니다. (이름을 통해 큰 데이터에 접근 할 때는 해쉬 테이블과 이진 트리 탐색을 사용할 수 있고, 적은 양의 데이터를 사용할 때는 간단한 리스트와 선형 탐색을 사용할 수 있습니다.)
FixedUpdate 함수는 최대한 가볍게 유지하세요. 이 함수들은 스크립트가 적용된 오브젝트별로 초당 50-100 번 정도 호출되기 때문에 성능 개선을 하기 좋은 대상입니다. 화면 갱신이 될 때 작업이 이루어지도록 하려면 Update 함수 안에 코드를 넣으세요.
가능하다면 불필요한 오브젝트의 스크립트들을 비활성화 시키도록 하세요.
게임 내에 넓은 레벨을 가지고 있고 적이 수 킬로 밖에 떨어져 있을 경우 카메라가 근접하기 전에는 AI 스크립트를 꺼두는 것이 좋습니다.
오브젝트를 켜고 끄는 좋은 방법은 gameObject.SetActiveRecursively(false)을 사용하고 구형, 박스형 충돌 메쉬를 tiggers처럼 이용하는 겁니다.
빈 Update 함수를 주의하세요. Assets 메뉴를 통해 새로운 스크립트를 생성했을 때 빈 Update()가 포함되어져 있을 겁니다. 성능상 비용이 소모되므로 불필요하다면 제거하세요. 이 성능상 비용은 모든 MonoBehaviour 스트립트 내에 재정의 가능한 모든 함수들에게서 발생하게 되는데 특히 Update나 FixedUpdate 함수가 주 대상 입니다.
GameObject는 대부분의 논리 컴포넌트에 의해 참조될 수 있습니다. 이론적으로 이런 식으로도 가능합니다. someGameObject.transform.gameObject.rigidbody.transform.gameObject.rigidbody.transform
하지만 상당히 불필요한 작업들이 이루어지게 됩니다. 오브젝트의 Transform이 필요하다면 스크립트의 앞부분에서 참조할 수 있도록 해두세요.
코루틴은 당신의 친구입니다. 코루틴은 적은 오버헤드만을 가지며 불필요하게 호출되는 Update 함수를 대체할 수 있습니다. 예를 들어 조명이 점점 밝아졌다 어두워졌다 하도록 만들 때 Update 함수보다는 코루틴을 사용할 수 있습니다. 이 경우 조명에 변화가 없는 대부분의 상황에서는 스크립트는 최소한의 성능만을 소모하게 됩니다. 만약 Update 함수에서 이런 작업이 이루어진다면 작업이 완료되었음에도 불필요한 작업이 지속적으로 진행될 수 있습니다.
정말 필요한게 아니라면 오브젝트를 검색하는 메소드를 사용하지마세요. 이 메소드에는 Gameobject.FindByTag()나 GameObject.GetComponent() 등은 물론 컴포넌트의 편의를 제공하는 속성들 (transform, light, etc...)을 포함합니다. 이 메소드들은 가능한 빠르게 작동하도록 최적화 되어 있지만 여전히 모든 관련된 오브젝트들을 검색하는 과정을 거칩니다. 가장 중요한 점은 Update()나 Fixedupdate() 같이 반복적으로 호출되는 곳에서 검색 메소드 사용을 피하는 겁니다.
한 번의 호출로 클래스내 멤버 변수에 결과를 저장해두고 필요할 때마다 접근해서 사용하도록 하세요.
왠만해서는 SendMessage() (또는 비슷한 함수)를 사용하지 마세요.
SendMessage() 는 함수를 직접 호출하는 것보다 적어도 100배는 더 느립니다.
그리고 오브젝트에서 사용하는 스크립트나 함수가 많아질수록 더욱 느려집니다.
만약 스크립트를 쉽게 찾을 수 있다면 찾아서 직접적으로 호출하도록 하세요.
JavaScript(그리고 Boo)의 duck typing은 적은 양이지만 연산이 필요합니다.
JavaScript 사용시 성능상 치명적인 부분은 선언된 변수의 타입을 명시적으로 물어보는 부분입니다.
(비록 이런 작업이 컴파일러에 의해 자동으로 추론 되어 상황이 달라질 수 있는 부분이 있습니다.)
원문 : http://wiki.unity3d.com/index.php?title=General_Performance_Tips