유니티의 작동원리
1.바이너리와 런타임
=========================================================================
C#과 런타임
=========================================================================
유니티로 게임을 만들 때, 개발자는 C#으로 동작을 프로그래밍한다.
C#은 컴파일러형 언어라 유니티에서 게임을 개발할 때 수시로 컴파일이 실행된다.
여기서 중요한 점이 있는데 C#은 전통적인 C 언어 등과 다른 점은 컴파일하면 기계에서 단독으로 실행되는 기계어가 아니라
.NET의 중간 언어 (Intermediate Language)IL로 컴파일이 된다.
IL로 변환된 실행 코드는 단독으로 실행할 수 없어서 .NET Framework의 런타임을 이용하여 순차적으로 기계어로 변환하면서 실행된다.

IL을 끼워 넣는 이유는 일단 기계어로 변환하면 단일 플랫폼에서만 실행할 수 있는 바이너리가 되기 때문이다.
IL이라면 어떤 플랫폼에서든 해당 플랫폼에 맞는 런타임만 준비하면 동작하게 되어 플랫폼마다 바이너리를 준비할 필요가 없다.
2.IL2CPP
유니티는 기본적으로 C#을 IL 코드로 컴파일하여 런타임에 실행하는데, 2015 년부터 일부 환경에서 문제가 발생하기 시작했다.
바로 iOS나 안드로이드에서 동작하는 앱의 64 비트 지원이다.
C#은 IL코드를 실행하기 위해 각각의 환경에서 동작할 수 있는 런타임이 필요한 것은 그 전까지 Mono를 포크하여 유니티 자체적으로 수정하여 사용하고 있었다.
즉 이 Mono를 64비트로 바꿔야 했는데 유니티는 이 방법대신 ILC2PP라는 기술을 개발해서 해당 문제를 해결했다.
IL코드를 C++로 변환하여 64bit에 대응하고 런타임에 기계어로 변환할 필요가 없어져 성능이 향상이 되었다.
빌드가 오래 걸리지만 64 비트 대응과 성능을 한 번에 해결할 수 있는 ILC2PP가 유니티의 핵심 기술이 되었다.
3.스레드
스레드는 프로그램의 실행 단위이며, 일반적으로 하나의 프로세스 안에 여러 개의 스레드를 생성하면서 처리가 진행된다.
CPU의 하나의 코어는 동시에 하나의 스레드만 처리할 수 있기 때문에 여러개의 스레드를 처리하기 위해 빠르게 스레드를 전환하면서 프로그램을 실행한다. 이를 컨텍스트 스위치 라고 하는데. 컨텍스트 스위치를 할 떄 오버헤드가 발생하여 처리 효율이 떨어진다.

프로그램 실행 시 기본이 되는 메인 스레드가 생성이 되고, 이 스레드에서 프로그램이 필요에 따라 다른 스레드를 생성하고 관리한다.
유니티의 게임 루프는 단일 스레드에서 동작하도록 설계되어서 사용자가 작성한 스크립트는 기본적으로 메인 스레드에서 작동하게 된다.
반대로 메인 스레드가 아닌 다른 곳에서 UnityAPI를 호출 하려고 하면 대부분의 API는 오류가 발생한다.
3.1 유니티 내부의 스레드
모든 처리를 메인 스레드에서 실행하면 프로그램 전체 처리에 시간이 오래 걸리게 된다.
여러개의 무거운 프로세스가 있고 그것이 상호 의존성이 없는 경우, 어느 정도 처리를 동기화하여 병렬 처리를 사용하고 있는데
그 중 하나가 렌더 스레드이다. 이름 그대로 렌더링 전용 스레드로, 메인 스레드에서 계산한 프레임의 렌더링 정보를 그래픽 명령어로 GPU 에 전송하는 역할을 한다.
메인 스레드와 렌더 스레드는 파이프라인처럼 실행되기 때문에 렌더 스레드가 처리하는 동안 다음 프레임의 계산이 시작된다. 그런데 만약 렌더 스레드 내에서 한 프레임을 처리하는 시간이 길어지면 다음 프레임의 렌더링 계산이 끝나도 시작하지 못하고 메인 스레드는 기다리게 된다.
게임 개발에서는 메인 스레드,렌더 스레드 중 어느 한쪽이 무거워지면 FPS가 떨어진다.
'최적화' 카테고리의 다른 글
| 튜닝<그래픽> (1) | 2025.06.17 |
|---|---|
| 튜닝 - 물리(Physics) (1) | 2025.06.15 |
| 에셋 관련 최적화 (1) | 2025.06.01 |
| 최적화<튜닝>의 기본상식1 (4) | 2025.05.11 |
| 유니티 프로젝트 튜닝 전, 중 주의사항 (0) | 2025.04.06 |