무엇을 찾고 계신가요?
Hero background image
매끄러운 게임플레이를 위한 향상된 물리 성능

이 글은 Unity 프로젝트를 위한 최적화 팁을 소개하는 시리즈 중 다섯 번째 글입니다. 더 적은 리소스로 더 높은 프레임 속도로 실행하기 위한 가이드로 활용하세요. 이러한 모범 사례를 시도해 본 후에는 시리즈의 다른 페이지도 확인해 보세요:

피직스는 복잡한 게임플레이를 만들 수 있지만 성능에 대한 대가가 따릅니다. 이러한 비용을 파악한 후에는 시뮬레이션을 조정하여 적절하게 관리할 수 있습니다. 이 팁을 사용하여 목표 프레임 속도를 유지하고 Unity에 내장된 피직스(NVIDIA PhysX)로 부드러운 재생을 만들 수 있습니다.

Unity 에디터의 쿠킹 옵션 인터페이스
콜라이더 확인

물리학에 사용되는 메시에는 쿠킹이라는 프로세스가 있습니다. 이렇게 하면 메시가 레이캐스트, 컨택트 등의 피직스 쿼리와 함께 작동할 수 있도록 메시가 준비됩니다.

메시콜라이더에는 메시의 피직스 유효성을 검사하는 데 도움이 되는 여러 쿠킹 옵션이 있습니다. 메시가 이러한 검사가 필요하지 않다고 확신하는 경우, 이를 비활성화하여 요리 시간을 단축할 수 있습니다.

메시콜라이더의 쿠킹 옵션에서 EnableMeshCleaning, WeldColocatedVertices, CookForFasterSimulation을 체크 해제합니다. 이 옵션은 런타임에 절차적으로 생성된 메시에는 유용하지만, 메시가 이미 적절한 트라이앵글을 가지고 있는 경우 비활성화할 수 있습니다.

PC를 대상으로 하는 경우 빠른 중간 단계 사용을 사용 하도록 설정하세요. 시뮬레이션 중간 단계에서 PhysX 4.1의 더 빠른 알고리즘으로 전환됩니다(물리 쿼리를 위해 잠재적으로 교차하는 작은 삼각형 집합을 좁히는 데 도움이 됩니다). 데스크톱이 아닌 플랫폼에서는 여전히 더 느린 알고리즘을 사용해야 합니다. R-trees.

메시 콜라이더는 일반적으로 비용이 많이 들기 때문에 더 복잡한 메시 콜라이더를 원시적이거나 단순화된 메시 콜라이더로 대체하여 원래 모양에 근접하도록 하는 것이 좋습니다.

자세한 내용은 요리 옵션 문서를 참조하세요.

BakeMeshJob 인터페이스
Use Physics.BakeMesh

게임플레이 중에 절차적으로 메시를 생성하는 경우 런타임에 메시 콜라이더를 생성할 수 있습니다. 그러나 메시 콜라이더 컴포넌트를 메시에 직접 추가하면 메인 스레드에서 피직스가 쿠킹됩니다. 이로 인해 상당한 CPU 시간이 소모될 수 있습니다.

Physics.BakeMesh를 사용하여 메시 콜라이더에 사용할 메시를 준비하고, 구운 데이터를 메시 자체와 함께 저장합니다. 이 메시를 참조하는 새 메시 콜라이더는 메시를 다시 베이크하지 않고 이 미리 베이크된 데이터를 재사용합니다. 이렇게 하면 나중에 씬 로드 시간이나 인스턴스화 시간을 줄이는 데 도움이 될 수 있습니다. 성능을 최적화하기 위해 메시 쿠킹을 다른 스레드로 오프로드할 수 있습니다. C# 잡 시스템.

여러 스레드에 걸쳐 메시를 굽는 방법에 대한 자세한 내용은 이 예시를 참조하세요.

물리 프로젝트 설정 인터페이스
설정 조정

플레이어 세팅에서 가능한 한 콜리전 메시 프리베이크에 체크합니다. 또한 콜리전 매트릭스 설정을 검토하여 플레이어와 게임 메카닉 오브젝트가 올바른 레이어에 있는지 확인하는 것이 좋습니다.

불필요한 레이어에 대한 트리거에서 콜백을 제거하면 큰 이득을 얻을 수 있으므로 레이어 콜리전 매트릭스를 단순화해 보세요. 프로젝트 세팅 > 피직스에서 피직스 세팅을 편집할 수 있습니다.

자세한 내용은 콜리전 매트릭스 문서를 참조하세요.

Unity 에디터의 고정 시간 단계 기본값
시뮬레이션 빈도 수정

피직스 엔진은 고정된 타임스텝에서 실행되는 방식으로 작동합니다. 프로젝트가 실행 중인 고정 속도를 확인하려면 편집 > 프로젝트 설정 > 시간으로 이동하세요.

고정 시간 간격 필드는 각 피직스 스텝에서 사용하는 시간 델타를 정의합니다. 예를 들어 기본값인 0.02초(20ms)는 초당 50프레임(fps) 또는 50Hz에 해당합니다.

Unity의 각 프레임은 다양한 시간이 걸리기 때문에 물리 시뮬레이션과 완벽하게 동기화되지는 않습니다. 엔진은 다음 피직스 타임스텝까지 계산합니다. 프레임이 약간 느리거나 빠르게 실행되는 경우 Unity는 경과 시간을 사용하여 적절한 타임스텝에서 물리 시뮬레이션을 실행할 시점을 파악합니다.

프레임을 준비하는 데 시간이 오래 걸리는 경우 성능 문제가 발생할 수 있습니다. 따라서 게임에서 많은 게임 오브젝트를 인스턴스화하거나 디스크에서 파일을 로드하는 등의 작업으로 인해 프레임이 급증하는 경우 실행에 40ms 이상이 걸릴 수 있습니다. 기본 20밀리초 고정 타임스텝을 사용하면 다음 프레임에서 두 개의 물리 시뮬레이션이 가변 타임스텝을 "따라잡기" 위해 실행됩니다.

물리 시뮬레이션이 추가되면 프레임 처리 시간이 더 늘어납니다. 저사양 플랫폼에서는 성능 저하로 이어질 수 있습니다.

후속 프레임을 준비하는 데 시간이 오래 걸리면 물리 시뮬레이션의 백로그도 길어집니다. 이로 인해 프레임이 더 느려지고 프레임당 실행해야 하는 시뮬레이션이 더 많아집니다. 그 결과 성능이 약화됩니다.

결국 피직스 업데이트 사이의 시간이 최대 허용 타임스텝을 초과할 수 있습니다. 이 컷오프가 지나면 Unity는 물리 업데이트를 삭제하기 시작하고 게임이 끊어집니다.

물리 성능 문제를 방지합니다:

  • 시뮬레이션 빈도를 줄입니다: 저사양 플랫폼의 경우 고정 시간 단계를 목표 프레임 속도보다 약간 높게 설정하세요. 예를 들어 모바일에서는 30fps에 0.035초를 사용합니다. 이렇게 하면 성능 저하를 방지하는 데 도움이 될 수 있습니다.
  • 최대 허용 타임스텝을 줄입니다: 이보다 작은 값(예: 0.1초)을 사용하면 물리 시뮬레이션 정확도가 약간 떨어지지만 한 프레임에 수행할 수 있는 물리 업데이트 횟수도 제한됩니다. 다양한 값을 실험하여 프로젝트의 요구 사항에 적합한 값을 찾아보세요.
  • 필요한 경우 물리 단계를 수동으로 시뮬레이션합니다: 피직스 설정에서 자동 시뮬레이션 옵션을 비활성화하고 프레임의 업데이트 단계에서 Physics.Simulate를 직접 호출합니다. 이를 통해 피직스 단계 실행 시기를 능동적으로 결정할 수 있습니다. 물리 시간을 시뮬레이션 시간과 동기화하기 위해 Time.deltaTime을 Physics.Simulate에전달합니다.
  • 참고: 이 접근 방식은 특히 복잡한 물리나 매우 가변적인 프레임 시간이 있는 장면에서 물리 시뮬레이션의 불안정성을 유발할 수 있습니다. 주의해서 사용하세요.

자세한 내용은 Physics.Simulate 문서를 참조하세요.

광범위 단계 인터페이스
큰 장면에 박스 가지치기를 사용

Unity 물리 엔진은 두 단계로 실행됩니다:

  • 광범위한 단계: 스윕 및 프루닝 알고리즘을 사용하여 잠재적 충돌을 수집합니다.
  • 좁은 위상: 엔진이 실제로 충돌을 계산할 때

광폭 위상 스윕 가지치기의 광폭 위상 기본 세팅(편집 > 프로젝트 세팅 > 피직스 > 광폭 위상 유형)은 일반적으로 평평하고 콜리더가 많은 월드에 오탐지를 생성할 수 있습니다. 씬이 크고 대부분 평평한 경우 이 문제를 피하고 자동 박스 가지치기 또는 멀티박스 가지치기 브로드페이즈로 전환하세요. 이 옵션은 월드를 그리드로 나누고, 각 그리드 셀은 스윕과 가지치기를 수행합니다.

멀티박스 가지치기 브로드페이즈에서는 월드 경계와 그리드 셀 수를 수동으로 지정할 수 있지만, 자동 박스 가지치기는 이 모든 것을 계산해 줍니다.

여기에서 피직스 프로퍼티 전체 목록을 확인하세요.

디폴트 솔버의 반복 횟수
솔버 반복 수정

특정 피직스 바디를 더 정확하게 시뮬레이션하려면 Rigidbody.solverIterations를 늘리세요. 이는 편집 > 프로젝트 세팅 > 피직스 > 디폴트 솔버 반복작업에서 찾을 수 있는 Physics.defaultSolverIterations를 오버라이드합니다.

피직스 시뮬레이션을 최적화하려면 프로젝트의 defaultSolveIterations에서 상대적으로 낮은 값을 설정하세요. 그런 다음 더 많은 디테일이 필요한 개별 인스턴스에 더 높은 커스텀 Rigidbody.solverIterations 값을 적용합니다.

Rigidbody.solverIterations에 대한 자세한 정보를 확인하세요.

장면에서 자동 동기화 비활성화
자동 변환 동기화 비활성화

트랜스폼을 업데이트하면 Unity는 이를 물리 엔진에 자동으로 동기화하지 않습니다. Unity는 트랜스폼을 누적하고 물리 업데이트가 실행되거나 사용자가 호출할 때까지 기다립니다. Physics.SyncTransforms.

트랜스폼과 피직스를 더 자주 동기화하려면, 다음과 같이 설정하면 됩니다. Physics.autoSyncTransformTrue 로 설정하면 됩니다 ( 프로젝트 세팅 > 피직스 > 트랜스폼 자동 동기화 에서도 찾을 수 있습니다). 이 옵션을 활성화하면 해당 트랜스폼의 모든 리지드바디 또는 콜리더와 그 자손이 자동으로 트랜스폼으로 업데이트됩니다.

그러나 꼭 필요한 경우가 아니라면 비활성화하세요. 일련의 연속적인 물리 쿼리(예: 레이캐스트)는 성능 저하로 이어질 수 있습니다.

Physics.SyncTransform에 대해 자세히 알아보세요.

단일 충돌 인스턴스
콜리전 콜백 재사용

콜리전 및 트리거 이벤트(OnCollisionEnter, OnCollisionStay, OnCollisionExit, OnTriggerEnter, OnTriggerStay, OnTriggerExit)는 이러한 함수를 구현하고 상호작용 기준을 충족하는 모든 모노비헤이비어에 대해 발동됩니다. 이러한 이벤트는 비활성화된 모노비헤이비어에도 전송됩니다.

따라서 불필요한 비어 있는 함수가 호출되므로 이러한 함수는 필요할 때만 구현하는 것이 좋습니다. 관련된 콜리더의 수에 따라 여러 번 호출될 수 있으므로 OnCollisionStay 및 OnTriggerStay에 특히 주의해야 합니다.

콜백MonoBehaviour.OnCollisionEnter, MonoBehaviour.OnCollisionStayMonoBehaviour.OnCollisionExit 도 콜리전 인스턴스를 파라미터로 받습니다. 이 콜리전 인스턴스는 관리되는 힙에 할당되며 가비지 컬렉션되어야 합니다.

생성되는 가비지 양을 줄이려면 Physics.reuseCollisionCallbacks( 프로젝트 세팅 > 피직스 > 콜리전 콜백 재사용에서 찾을 수 있습니다). 이 옵션을 활성화하면 Unity는 각 콜백에 하나의 콜리전 페어 인스턴스만 할당합니다. 이렇게 하면 가비지 컬렉터(GC)의 낭비가 줄어들고 전반적인 성능이 향상됩니다.

참고: 포스트 프로세싱을 위해 콜리전 콜백 외부에서 콜리전 인스턴스를 참조하는 경우, 콜리전 콜백 재사용을 비활성화해야 합니다.

Physics.reuseCollisionCallback에 대해 자세히 알아보세요.

스태틱 콜리더 이동

스태틱 콜라이더는 콜라이더 컴포넌트가 있지만 리지드바디가 없는 게임 오브젝트입니다. 이름과 달리 스태틱 콜라이더를 움직일 수 있습니다.

피직스 바디의 위치를 수정하고 위치 변경 사항을 누적한 다음 피직스 업데이트 전에 동기화하기만 하면 되며, 이동을 위해 스태틱 콜라이더에 리지드바디 컴포넌트를 추가할 필요는 없습니다. 하지만 스태틱 콜리더가 다른 물리 바디와 더 복잡한 방식으로 상호작용하도록 하려면 키네마틱 리지드바디. 사용 Rigidbody.positionRigidbody.rotation 을 사용하여 트랜스폼 컴포넌트에 액세스하는 대신 이동합니다. 이렇게 하면 물리 엔진에서 더 예측 가능한 동작을 보장할 수 있습니다.

참고: 2D 피직스에서는 트리 리빌드에 시간이 많이 걸리므로 스태틱 콜리더를 움직이지 마세요.

리지드바디에 대해 자세히 알아보세요.

비할당 쿼리 사용

특정 거리, 특정 방향 내의 충돌기를 감지하고 수집하려면 다음과 같은 레이캐스트 및 기타 물리 쿼리를 사용합니다. BoxCast.

여러 콜라이더를 배열로 반환하는 피직스 쿼리는 다음과 같습니다. 오버랩스피어오버랩박스와 같은 물리 쿼리는 관리되는 힙에 해당 오브젝트를 할당해야 합니다. 즉, 가비지 컬렉터는 결국 할당된 객체를 수집해야 하므로 잘못된 타이밍에 발생하면 성능이 저하될 수 있습니다.

이 오버헤드를 줄이려면 해당 쿼리의 비할당 버전을 사용하세요. 예를 들어 오버랩스피어를 사용하여 한 점 주변의 모든 잠재적 콜리더를 모으는 경우, 반드시 다음을 사용해야 합니다. OverlapSphereNonAlloc. 이를 통해 버퍼처럼 작동하는 콜라이더 배열(결과 매개변수)을 전달할 수 있습니다.

비할당 메서드는 가비지 생성 없이 작동합니다. 그렇지 않으면 해당 할당 방법과 같이 작동합니다. 비할당 방식을 사용할 때는 충분한 크기의 결과 버퍼를 정의하는 것을 잊지 마세요. 버퍼는 공간이 부족하면 커지지 않습니다.

비할당 메서드 문서에서 자세히 알아보세요.

레이캐스팅을 위한 일괄 쿼리

레이캐스트 쿼리를 실행할 수 있지만 Physics.Raycast를 사용하여 레이캐스트 쿼리를 실행할 수 있지만 상당한 양의 CPU 시간이 소요될 수 있습니다. 레이캐스트 작업의 수가 많은 경우(예: 10,000명의 상담원에 대한 가시선 계산) 특히 그렇습니다.

사용 레이캐스트 커맨드 를 사용하여 C# 잡 시스템을 사용하여 쿼리를 일괄 처리합니다. 이렇게 하면 메인 스레드에서 작업이 오프로드되어 레이캐스트가 비동기식으로 병렬로 발생할 수 있습니다.

레이캐스트 커맨드 문서에서 예시를 참조하세요.

물리 디버거 인터페이스
피직스 디버거로 시각화하기

피직스 디버그(창 > 분석 > 피직스 디버거)을 사용하여 문제가 있는 콜리더 또는 불일치 문제를 해결할 수 있습니다. 이 창에는 서로 충돌할 수 있는 게임 오브젝트를 색상으로 구분한 표시기가 표시됩니다.

자세한 내용은 피직스 디버그 시각화 페이지를 참조하세요.

유니티 키 아트 21 11
무료 전자책 받기

가장 포괄적인 가이드 중 하나로, PC 및 콘솔용 게임을 최적화하는 방법에 대한 80개 이상의 실행 가능한 팁을 모았습니다. 유니티의 성공 및 가속화 솔루션 전문 엔지니어가 작성한 이 심층적인 팁은 Unity를 최대한 활용하고 게임 성능을 향상하는 데 도움이 될 것입니다.

이 콘텐츠가 마음에 드셨나요?