CPU 성능 추천 사항
캐시 참조
GetComponent<T>() 및 Camera.main과 같은 반복적인 함수 호출이 포인터를 저장하는 메모리 비용에 비해 더 비싸기 때문에 초기화 시 모든 관련 구성 요소 및 GameObjects에 대한 참조를 캐싱하는 것이 좋습니다. . Camera.main은 아래의 FindGameObjectsWithTag() 만 사용합니다. 이는 "MainCamera" 태그를 사용하여 장면 그래프에서 카메라 개체를 검색하지만 많은 비용이 들어갑니다.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
private Camera cam;
private CustomComponent comp;
void Start()
{
cam = Camera.main;
comp = GetComponent<CustomComponent>();
}
void Update()
{
// Good
this.transform.position = cam.transform.position + cam.transform.forward * 10.0f;
// Bad
this.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 10.0f;
// Good
comp.DoSomethingAwesome();
// Bad
GetComponent<CustomComponent>().DoSomethingAwesome();
}
}
비용이 많이 드는 작업 방지
1. LINQ 사용 방지
LINQ는 깨끗하고 읽기 및 쓰기가 쉬울 수 있지만 알고리즘을 수동으로 작성한 경우보다 일반적으로 더 많은 계산과 메모리가 필요합니다.
// Example Code
using System.Linq;
List<int> data = new List<int>();
data.Any(x => x > 10);
var result = from x in data
where x > 10
select x;
2. 일반 Unity API
일부 Unity API는 유용하지만 실행 비용이 많이 들 수 있습니다. 이러한 API 중 대부분은 전체 장면 그래프에서 일치하는 몇 가지 GameObjects 목록을 찾습니다. 일반적으로 런타임에 참조를 추적하기 위해 참조를 캐싱하거나 GameObjects에 대한 관리자 구성 요소를 구현하여 이러한 작업을 방지할 수 있습니다.
GameObject.SendMessage()
GameObject.BroadcastMessage()
UnityEngine.Object.Find()
UnityEngine.Object.FindWithTag()
UnityEngine.Object.FindObjectOfType()
UnityEngine.Object.FindObjectsOfType()
UnityEngine.Object.FindGameObjectsWithTag()
UnityEngine.Object.FindGameObjectsWithTag()
3. boxing에 주의
boxing은 C# 언어 및 런타임의 핵심 개념입니다. 이는 char, int, bool 등과 같은 값 형식 변수를 참조 형식 변수로 래핑하는 프로세스입니다. 값 형식 변수가 "boxed"가 되면 관리형 힙에 저장된 System.Object에 래핑됩니다. 메모리가 할당되며, 결국에는 삭제 시 가비지 수집기에서 처리해야 합니다. 이러한 할당 및 할당 취소는 성능 비용을 발생시키며, 많은 시나리오에서 필요하지 않거나 비용이 더 저렴한 대안으로 쉽게 대체할 수 있습니다.
boxing을 방지하려면 숫자 유형과 구조체(Nullable<T> 포함)를 저장하는 변수, 필드 및 속성의 형식이 개체를 사용하는 대신 int, float? 또는 MyStruct와 같은 특정 형식의 강력한 형식이어야 합니다. 이러한 개체를 목록에 넣는 경우 List<object> 또는 ArrayList가 아닌 List<int>와 같은 강력한 형식의 목록을 사용해야 합니다.
// boolean value type is boxed into object boxedMyVar on the heap
bool myVar = true;
object boxedMyVar = myVar;
반복 코드 경로
초당 여러 번 실행되는 반복 Unity 콜백 함수(즉, 업데이트)는 신중하게 작성해야 합니다. 여기서 비용이 많이 드는 작업은 성능에 크고 일관된 영향을 미칠 수 있습니다.
1. 빈 콜백 함수
아래 코드는 애플리케이션에 남겨 두는 것이 무해한 것처럼 보일 수 있지만, 특히 모든 Unity 스크립트가 Update 메서드로 자동 초기화되기 때문에 이러한 빈 콜백은 비용이 많이 들 수 있습니다. Unity는 UnityEngine 코드와 애플리케이션 코드 간에 비관리/관리 코드 경계를 넘나들며 작동합니다. 이 브리지를 통해 컨텍스트를 전환하는 것은 실행하는 작업이 없더라도 비용이 매우 많이 듭니다. 반복되는 빈 Unity 콜백이 있는 구성 요소가 포함된 100개의 GameObjects가 앱에 있는 경우 특히 문제가 됩니다.
Update()는 이 성능 문제의 가장 일반적인 증상이지만 다른 Unity 콜백(예: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage() 등)은 나쁘지 않은 경우에도 마찬가지로 나쁠 수 있습니다.
void Update()
{
}
2. 프레임당 한 번 실행되도록 하는 작업
다음 Unity API는 많은 홀로그램 앱의 일반적인 작업입니다. 이러한 함수의 결과는 항상 가능한 것은 아니지만 일반적으로 한 번 계산될 수 있으며, 지정된 프레임에 대해 애플리케이션 전체에서 다시 사용할 수 있습니다.
a) 각 구성 요소에서 반복적이고 동일한 Raycast 작업을 수행하는 대신, 장면에서 Raycast를 응시하도록 처리한 다음, 이 결과를 다른 모든 장면 구성 요소에서 다시 사용하는 전용 Singleton 클래스 또는 서비스를 사용하는 것이 좋습니다. 일부 애플리케이션에는 다른 원본 또는 다른 LayerMask에 대한 Raycast가 필요할 수 있습니다.
UnityEngine.Physics.Raycast()
UnityEngine.Physics.RaycastAll()
b) Start() 또는 Awake()에서 캐싱 참조를 통해 Update()와 같은 반복적인 Unity 콜백에서 GetComponent() 작업을 사용하도록 방지합니다.
UnityEngine.Object.GetComponent()
c) 가능한 경우 초기화 시 모든 개체를 인스턴스화하고 개체 풀링을 사용하여 애플리케이션의 런타임 전체에서 GameObjects를 재활용하고 다시 사용하는 것이 좋습니다.
UnityEngine.Object.Instantiate()
3. 인터페이스 및 가상 구문 사용 방지
직접 개체보다 인터페이스를 통해 함수 호출을 호출하거나 가상 함수를 호출하는 경우 종종 직접 구문 또는 직접 함수 호출을 활용하는 것보다 훨씬 비용이 많이 들 수 있습니다. 가상 함수 또는 인터페이스가 필요하지 않은 경우 이를 제거해야 합니다. 그러나 이러한 방법의 성능 결과는 이를 사용하여 개발 협업, 코드 가독성 및 코드 유지 관리가 간소화되는 경우 절충할 만한 가치가 있습니다.
일반적으로 이 멤버를 덮어쓸 필요가 있는 경우에만 필드 및 함수를 가상으로 표시하는 것이 좋습니다. UpdateUI() 메서드와 같이 프레임당 여러 번 또는 한 번 호출되는 빈도가 높은 코드 경로에서는 특히 주의해야 합니다.
4. 값으로 구조체 전달 방지
클래스와 달리 구조체는 값 형식이며, 함수에 직접 전달되면 해당 내용이 새로 만든 인스턴스에 복사됩니다. 이 복사본으로 인해 CPU 비용과 스택의 추가 메모리가 추가됩니다. 작은 구조체의 경우 효과가 최소화되므로 허용됩니다. 그러나 모든 프레임을 반복적으로 호출하는 함수와 큰 구조체를 사용하는 함수의 경우 가능하면 함수 정의를 참조로 전달하도록 수정합니다.
Class 와 Struct 의 차이에 대한 설명 링크
메서드에 대한 구조체 전달과 클래스 참조 전달 간의 차이점을 이해하는 방법 - C# 프로그래밍 가
C#에서 메서드에 구조체를 전달하는 것과 메서드에 클래스 인스턴스를 전달하는 것은 다릅니다. 이 예제에서는 값으로 전달된 구조체 및 클래스 인스턴스를 보여줍니다.
docs.microsoft.com
기타
- Physics
a) 일반적으로 물리학을 향상시키는 가장 쉬운 방법은 Physics에 소요되는 시간 또는 초당 반복 횟수를 제한하는 것입니다. 이렇게 하면 시뮬레이션 정확도가 떨어집니다. Unity의 TimeManager를 참조하세요.b) Unity의 collider 형식에는 매우 다양한 성능 특징이 있습니다. 아래 순서는 왼쪽에는 성능이 가장 높은 collider, 오른쪽에는 성능이 가장 낮은 collider의 순서로 나열되어 있습니다. 기본 collider보다 실질적으로 더 비싼 메시 collider를 사용하지 않도록 방지하는 것이 중요합니다.자세한 내용은 Unity Physics 모범 사례를 참조하세요.구 < 캡슐 < 상자 <<< 메시(볼록) < 메시(비볼록) - 애니메이션
Animator 구성 요소를 사용하지 않도록 설정하여 유휴 애니메이션을 사용하지 않도록 설정합니다(게임 개체를 사용하지 않도록 설정하면 동일한 효과가 없음). 애니메이터가 동일한 값으로 설정하는 반복에 있는 디자인 패턴을 사용하지 않도록 방지합니다. 이 기술에는 애플리케이션에 영향을 주지 않지만 상당한 오버헤드가 있습니다.
참고 링크
https://docs.unity3d.com/Manual/MecanimPeformanceandOptimization.html
Unity - Manual: Performance and optimization
Retargeting of Humanoid animations Performance and optimization This page contains some tips to help you obtain the best performance in Unity, covering the animation system and run-time optimizations. Note: For tips on modeling your character in a 3d appli
docs.unity3d.com
3. 복잡한 알고리즘
애플리케이션에서 역운동학, 경로 찾기 등과 같은 복잡한 알고리즘을 사용하는 경우 더 간단한 방법을 찾거나 해당 성능과 관련된 설정을 조정합니다.
CPU-GPU 성능 추천 사항
정적 일괄 처리
Unity는 많은 정적 개체를 일괄 처리하여 GPU에 대한 그리기 호출을 줄일 수 있습니다. 정적 일괄 처리는 1) 동일한 재질을 공유하고 2) 모두 Static으로 표시되는 Unity의 Renderer 개체 대부분에서 작동합니다(Unity에서 개체를 선택하고 검사기 오른쪽 위의 확인란을 선택함). Static으로 표시된 GameObjects는 애플리케이션의 런타임 전체에서 이동할 수 없습니다. 따라서 정적 일괄 처리는 거의 모든 개체를 배치, 이동, 크기 조정해야 하는 HoloLens에서 활용하기가 어려울 수 있습니다. 몰입형 헤드셋의 경우 정적 일괄 처리를 통해 그리기 호출을 크게 줄여 성능을 향상시킬 수 있습니다.
자세한 내용은 Unity의 그리기 호출 일괄 처리에서 정적 일괄 처리를 참조하세요.
https://docs.unity3d.com/Manual/DrawCallBatching.html
Unity - Manual: Draw call batching
Creating shaders that support GPU instancing Draw call batching Draw call batching is a draw call optimization method that combines meshes so that Unity can render them in fewer draw calls. Unity provides two built-in draw call batching methods: Static bat
docs.unity3d.com
기타 기술
여러 GameObjects에서 동일한 재질을 공유할 수 있는 경우에만 일괄 처리를 수행할 수 있습니다. 일반적으로 GameObjects에는 각 Material에 고유한 질감이 있어야 하므로 이 기술이 차단됩니다. Texture를 하나의 큰 Texture로 결합하는 것이 일반적이며, 이를 질감 아틀라싱(Texture Atlasing)이라고 합니다.
https://en.wikipedia.org/wiki/Texture_atlas
Texture atlas - Wikipedia
en.wikipedia.org
또한 가능하고 합리적인 경우 메시를 하나의 GameObject로 결합하는 것이 좋습니다. 하나의 Renderer 아래에 결합된 메시를 제출하는 것과 비교하여 Unity의 각 Renderer에는 연결된 그리기 호출이 있습니다.
GPU 성능 추천 사항
대역폭 및 유효 노출률
GPU에서 프레임을 렌더링할 때 애플리케이션은 메모리 대역폭 또는 유효 노출률에 의해 제한됩니다.
- 메모리 대역폭은 GPU가 메모리에서 수행할 수 있는 읽기 및 쓰기 비율입니다.
- Unity의 편집>프로젝트 설정>품질 설정에서 텍스처 품질을 변경합니다.
https://docs.unity3d.com/Manual/class-QualitySettings.html
- Unity의 편집>프로젝트 설정>품질 설정에서 텍스처 품질을 변경합니다.
Unity - Manual: Quality
Script Execution Order settings Quality Switch to Scripting Unity allows you to set the level of graphical quality it attempts to render. Generally speaking, quality comes at the expense of framerate and so it may be best not to aim for the highest quality
docs.unity3d.com
- 유효 노출률은 GPU가 초당 그릴 수 있는 픽셀을 나타냅니다.
- Unity에서 XRSettings.renderViewportScale 속성을 사용합니다.
- https://docs.unity3d.com/ScriptReference/XR.XRSettings-renderViewportScale.html
Unity - Scripting API: XR.XRSettings.renderViewportScale
Valid range is 0.0 to 1.0. This value can be changed at runtime without reallocating eye textures. Therefore it is useful for dynamically adjusting eye render resolution. This value cannot be changed while cameras are being rendered. Attempts to change the
docs.unity3d.com
다각형 수 감소
다각형 수는 다음 중 하나를 수행하면 줄어듭니다.
- 장면에서 개체 제거
- 지정된 메시의 다각형 수를 줄이는 자산 부분 제거
- 동일한 기하 도형의 낮은 다각형 버전을 사용하여 멀리 떨어진 개체를 렌더링하는 애플리케이션에 LOD(세부 정보 수준) 시스템 구현
https://docs.unity3d.com/Manual/LevelOfDetail.html
Unity - Manual: Level of Detail (LOD) for meshes
Level of Detail (LOD) for meshes This page contains information on level of detail (LOD) for meshes. For information on LOD for shadersA program that runs on the GPU. More infoSee in Glossary, see SubShader LOD value. Level of detail (LOD) is a technique r
docs.unity3d.com
메모리 추천 사항
과도한 메모리 할당 & 할당 취소 작업은 홀로그램 애플리케이션에 부정적인 영향을 줄 수 있으므로 일관성 없는 성능, 고정된 프레임 및 기타 부정적인 동작이 발생할 수 있습니다. 메모리 관리는 가비지 수집기를 통해 제어되므로 Unity에서 개발하는 경우 메모리 고려 사항을 이해하는 것이 특히 중요합니다.
가비지 수집
실행 중에 더 이상 범위에 있지 않은 개체를 분석하기 위해 GC를 활성화하고 메모리를 해제해야 할 때 홀로그램 앱에서 GC(가비지 수집기)에 대한 처리 컴퓨팅 시간을 잃게 되기 때문에, 다시 사용할 수 있도록 설정할 수 있습니다. 지속적인 할당 및 할당 취소는 일반적으로 가비지 수집기를 더 자주 실행해야 하므로 성능과 사용자 환경이 저하됩니다.
과도한 가비지 컬렉션으로 이어지는 가장 일반적인 사례 중 하나는 Unity 개발에서 구성 요소 및 클래스에 대한 참조를 캐싱하지 않는 것입니다. 모든 참조는 Start() 또는 Awake() 중에 캡처되고, Update() 또는 LateUpdate()와 같은 이후 함수에서 다시 사용되어야 합니다.
기타 빠른 팁:
- 런타임에 복잡한 문자열을 동적으로 빌드하려면 StringBuilder C# 클래스를 사용합니다.
https://docs.microsoft.com/ko-kr/dotnet/api/system.text.stringbuilder
StringBuilder 클래스 (System.Text)
변경할 수 있는 문자열을 나타냅니다. 이 클래스는 상속될 수 없습니다.
docs.microsoft.com
- 앱의 모든 빌드 버전에서 계속 실행되므로 더 이상 필요하지 않은 Debug.Log()에 대한 호출을 제거합니다.
- 홀로그램 앱에 일반적으로 많은 메모리가 필요한 경우 로드 또는 전환 화면을 표시할 때와 같이 로드 단계 중에 System.GC.Collect()를 호출하는 것이 좋습니다.
https://docs.microsoft.com/ko-kr/dotnet/api/system.gc.collect
GC.Collect 메서드 (System)
가비지 컬렉션을 수행하도록 합니다.
docs.microsoft.com
개체 풀링
개체 풀링은 지속적인 개체 할당 및 할당 취소에 드는 비용을 줄이는 데 널리 사용되는 기술입니다. 이 작업을 수행하려면 시간이 지남에 따라 개체를 지속적으로 만들고 삭제하는 대신, 동일한 개체의 대량 풀을 할당하고 이 풀에서 사용 가능한 비활성 인스턴스를 다시 사용합니다. 개체 풀은 앱 중에 수명이 가변적인 다시 사용할 수 있는 구성 요소에 적합합니다.
시작 성능
앱을 더 작은 장면으로 시작한 다음, SceneManager.LoadSceneAsync 를 사용하여 나머지 장면을 로드하는 것을 고려합니다. 이렇게 하면 앱이 최대한 빨리 대화형 상태로 전환될 수 있습니다. 새 장면이 활성화되는 동안 높은 CPU 스파이크가 발생할 수 있으며 렌더링된 콘텐츠가 끊기거나 장애가 발생할 수 있습니다. 이 문제를 해결하는 한 가지 방법은 로드되는 장면에서 AsyncOperation.allowSceneActivation 속성을 "false"로 설정하고, 장면이 로드될 때까지 기다리고, 화면을 검은색으로 지운 다음, "true"로 다시 설정하여 장면 활성화를 완료하는 것입니다.
시작 장면을 로드하는 동안 사용자에게 홀로그램 시작 화면이 표시됩니다.
SceneManager.LoadSceneAsync 관한 유니티 문서
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadSceneAsync.html
Unity - Scripting API: SceneManagement.SceneManager.LoadSceneAsync
You can provide the full Scene path, the path shown in the Build Settings window, or just the Scene name. If you only provide the Scene name, Unity loads the first Scene in the list that matches. If you have multiple Scenes with the same name but different
docs.unity3d.com
참고
'정리 > UNITY' 카테고리의 다른 글
InvokeRepeating (반복 재생 기능) (0) | 2022.05.21 |
---|---|
유니티 게임 내 Scripts 최적화 (Unity Article) (0) | 2022.04.28 |
Menu_UI 기능 구현 (0) | 2022.04.25 |
IL2CPP (0) | 2022.03.19 |
효율적 UI_Component 바인딩 (0) | 2022.03.08 |