Unity 검색

Improving and expanding use cases: Physics changes in Unity 2022.2 | Hero image
Improving and expanding use cases: Physics changes in Unity 2022.2 | Hero image
공유

Is this article helpful for you?

Thank you for your feedback!

아무리 성공적인 툴이라도 최신 사용 사례에 맞게 조정해 나가며 발전을 거듭해야 합니다. 이러한 신념을 바탕으로 2022.2 테크 스트림에서는 Unity 에디터의 기존 물리 기능에 대한 업데이트를 제공하며, 이번 변경 사항은 각각 기존 사용 사례에 대한 적합성을 개선하는 동시에 동일한 접근 방식을 사용하는 새로운 방식을 개척하는 데 목표를 두고 있습니다.

물리 툴 개선: 주요 내용

물리 쿼리

Physics.Raycast와 같은 물리 쿼리는 특정 위치에서 물리 오브젝트와 그 중첩을 찾아낼 수 있는 다용도 툴입니다. 이러한 중첩 정보는 센서, 커스텀 물리력과 같은 애플리케이션별 로직에서 입력의 역할을 합니다. 이는 많은 애플리케이션의 핵심이므로, 2022.2 업데이트는 Unity에서 배치 쿼리처럼 더 많은 쿼리 유형이 실행될 수 있도록 함으로써 쿼리 효율성을 더욱 더 증대하기 위한 일련의 개선 사항을 제공합니다.

물리 쿼리는 쉽게 사용할 수 있었으나 더 많은 바디와 콜라이더, 커스텀 에이전트로 시뮬레이션이 확장될 때에만 드러나는 특수한 단점이 하나 있었습니다. 바로 호출된 스레드(메인 스레드)에서만 실행된다는 점입니다. 이로 인해 각각의 개별 쿼리가 빠르게 실행되어도 많은 쿼리를 실행하면 성능 병목 현상이 발생하는 경향이 있습니다. 유니티는 이 문제를 해결하기 위해 새로운 버퍼를 노출시키는 배치 물리 쿼리를 구축했습니다. 물리 쿼리를 이 새 버퍼에 추가할 수 있으며, 이렇게 하면 메인 스레드에서 다른 쿼리가 계산되고 있을 때 다른 스레드에서 쿼리가 실행되도록 이 버퍼에서 쿼리 일정을 예약할 수 있습니다.

이번 릴리스 이전까지는 배치 물리 쿼리가 매번 단일 히트만 반환하는 쿼리만 실행할 수 있었으며 이는 잠재적인 사용 사례에 상당한 제약이 되었습니다. 이제 여러 히트를 반환하는 쿼리를 실행하는 방식이 도입됩니다.

그 작동 방식을 이해하기 위해 배치 레이캐스트를 예로 들겠습니다. 2022.12022.2RaycastCommand 클래스를 비교하면 layerMaskmaxHits 파라미터가 없어지고 queryParameters 파라미터가 새롭게 추가되었음을 알 수 있습니다. layerMask 파라미터는 이제 그 어느 때보다도 많은 파라미터가 보관된 새로운 구조의 일부이며, 쿼리를 통해 단일 메시에서 여러 히트가 발생하도록 하는 신규 옵션이 포함되어 있습니다. 또한 maxHits 파라미터가 커맨드 생성자에서 batch schedule 함수로 이동했습니다. 이러한 변경을 통해 이제 배치 일정이 예약될 때 커맨드 배열을 반복할 필요가 없으므로 메모리 초기화를 늦출 수 있습니다. 이는 작업 체이닝 시 유용할 수 있는데, 왜냐하면 이제 데이터가 있을 때 다른 작업이 커맨드 버퍼를 채울 수 있기 때문입니다.

물론 레이캐스트에 국한되는 것은 아닙니다. 다른 배치 쿼리도 모두 업데이트되어 이제 shape castsshape overlaps가 커맨드당 여러 히트를 반환할 수 있습니다.

컨택트

Unity는 사용자 코드에서 구현해야 하는 세 가지 OnContact 콜백을 통해 일련의 최신 물리 컨택트에 대한 액세스 권한을 제공합니다. 이 세 가지 콜백은 새 컨택트, 지속적인 컨택트, 유실된 컨택트에 대한 알림을 전송하며, 이는 유연성과 사용성 향상을 지원했던 Unity 초기의 뛰어난 모듈 단위 접근 방식입니다.

하지만 Unity 프로젝트가 더 커지고 보다 정교해지면서 이러한 접근 방식을 제대로 확장하기가 어려워졌습니다. 네이티브 코드에서 이러한 콜백을 호출하고 컨택트 데이터를 관리형 코드로 마샬링함에 따라 최적화되지 않은 GC(가비지 컬렉터) 메모리 사용 패턴이 발생했습니다. 다만 이러한 문제는 2018.3 테크 스트림에서 해당 콜백 호출 시 Collision 클래스 인스턴스를 재사용함으로써 대부분 해결되었습니다. 하지만 이전에 해결되지 않았던 심각한 성능 문제도 유발되어 대형 프로젝트에서 대규모의 컨택트 컬렉션을 렌더링하는 것은 거의 불가능했습니다.

유니티는 얼마 전에 컨택트 수정 기능을 작업하던 중, 기존의 OnContact 콜백이 아닌 스레드 형식의 컨택트 수정 인터페이스를 사용하면 약 4배 빨리 컨택트를 읽을 수 있다는 사실을 알아냈습니다. 스레딩을 논외로 했을 때 이처럼 극적인 성능 증대의 근본 원인은 컨택트 수정 시 컨택트 데이터 배열에 대한 직접 액세스 권한이 스크립트에 제공된다는 것이었습니다.

컨택트 데이터 배열에 대한 직접 액세스가 성능 향상으로 이어지는 이유는 다음과 같습니다.

  • 각 컨택트 페어당 Collision 클래스 인스턴스를 생성할 필요가 없습니다.
  • 관리형 코드에서 컨택트를 완벽하게 반복할 수 있습니다. 반면, OnContact 접근 방식은 각 컨택트 페어에 대해 컨택트 데이터를 수신하는 관리형 함수를 호출하는 네이티브 코드를 사용했습니다.

네이티브-관리형 호출은 적절히 확장되지 않습니다. 이러한 점을 반영하여 최신 릴리스에서는 컨택트 수정 프로세스를 바탕으로 컨택트 데이터를 읽기 위한 더 빠르고 새로운 방법을 제공합니다.

컨택트에 액세스하려면 새 Physics.ContactEvent 이벤트를 사용해 보세요. 이는 각 물리 씬에 대해 한 번 호출되며 대규모의 연속 배열에서 최신 컨택트 페어 전체에 대한 액세스 권한을 제공합니다. 이 배열의 요소에 액세스하는 것은 고속 직접 메모리 연산이며, 이때 관리형 및 네이티브 컨텍스트 사이에서 무언가를 전달할 필요가 없습니다. 또한, 복수 코어를 활용하기 위해 C# 잡을 사용하여 컨택트를 반복할 수 있습니다. 이것이 기존 OnContact 콜백보다 훨씬 더 빠른 이유입니다.

콜백과 관련해서는 C#에서 기존 콜백 경로를 재구현하기도 했으며, 이제 내부적으로 Physics.ContactEvent를 사용합니다. 이렇게 하면 관리형과 네이티브 사이에서 컨트롤이 바운스되어야 하는 횟수가 줄어, 새로운 방식으로 아직 업그레이드되지 않은 기존 프로젝트에서 속도가 향상됩니다. 이는 콜백 자체의 기능에 영향을 주지 않습니다.

충돌 오버라이드

Unity는 레이어 기반 충돌 시스템을 사용합니다. 두 콜라이더 사이의 컨택트를 발견하면 물리 시스템은 Layer Collision Matrix를 사용하여 충돌이 실제로 허용되는지 여부를 확인합니다. 또한 추가 스크립트 함수인 Physics.IgnoreCollision이 있어 특정 콜라이더 페어를 서로 무시하는 것으로 표시할 수 있습니다.

이 접근 방식의 단점은 게임 오브젝트가 단일 레이어에만 속할 수 있다는 것으로서, 총 32레이어만 존재할 수 있습니다(렌더링 등 다른 하위 시스템에서 사용하는 범용 레이어임에 유의). 이 설정 때문에 시스템의 유연성은 그리 높지 않습니다.

유연성을 개선하기 위해 콜라이더 및 리지드바디당 레이어 설정을 오버라이드하는 간단한 방법을 추가했습니다.

BoxCollider with the Layer Overrides section expanded.
Layer Overrides 섹션이 확장된 상태의 Box Collider

이 변경 사항을 통해 이제 물리 오브젝트가 레이어 매트릭스 설정을 오버라이드할 수 있으며, 충돌할 레이어와 무시할 레이어를 명시적으로 지정할 수 있습니다.

시뮬레이션 업데이트

기본적으로 물리 시뮬레이션은 Time.fixedDeltaTime 프로퍼티에 의해 설정된 대로 고정된 주기에 따라 자동으로 수행됩니다. 2017.1 릴리스에서는 시뮬레이션을 수동으로 제어할 수 있는 Physics.Simulate 메서드를 공개했습니다. 이제 애플리케이션에 적합한 타임 스테핑 메커니즘을 사용하고, 타임 스파이크에 대한 커스텀 반응을 디자인하는 등의 작업을 할 수 있습니다. 이 기능에는 물리가 자동으로 실행되도록 할지 스크립트 기반으로 실행되도록 할지 제어하는 에디터 설정이 포함됩니다.

최신 릴리스에는 가변 델타 시간을 통해 물리가 모든 게임 틱마다 시뮬레이션될 수 있도록 하는 신규 옵션이 추가되었습니다. 모든 틱마다 물리를 시뮬레이션하면 모션이 항상 부드러워져 보간을 사용할 필요가 없다는 이점이 생깁니다. 또한 스테핑 스키마가 매우 단순하여 고정 델타 시간 캐치업이 필요하지 않습니다.

하지만 수치 알고리즘에서 원활하고 작은 델타가 필요한 경우도 있기 때문에, 이러한 시뮬레이션이 비결정론적이거나 부정확할 수 있다는 단점이 있을 수도 있습니다. 이러한 이유로, 이 모드는 높고 안정적인 프레임 속도가 유지되는 프로젝트에만 사용할 것을 권장합니다.

The new simulation mode is available in the Physics settings.
Physics 설정에서 새 시뮬레이션 모드 사용 가능

아울러, 이제 추가 물리 씬을 사용할 때 보간과 외삽을 사용할 수 있습니다. 필요한 경우 보간과 외삽을 적용할 수 있도록 새로운 메서드 PhysicsScene.InterpolateBodies를 공개했습니다.

사용자 피드백 반영

유니티는 사용자 요청에 따른 변경 사항을 최신 릴리스에 최대한 많이 포함하고자 항상 노력하고 있습니다. 다음은 포럼을 통해 얼리 어답터 사용자들이 요청한 변경 사항의 목록입니다.

  • 조인트 구동력 애플리케이션 모드: 일반 조인트가 새로운 Use Acceleration 프로퍼티를 가집니다. 활성화하면 구동력 대신 연결된 바디 모두에 대해 가속도가 설정됩니다. 연결된 바디의 질량이 서로 다른 경우 이 모드를 쉽게 설정할 수 있습니다. ArticulationBody 구동을 설정하여 구동력 또는 가속도를 적용하거나, 타겟의 위치나 속도를 바로 설정할 수 있습니다.
ArticulationBody where the X Drive section changes based on the Drive Type setting.
Drive Type 설정에 따라 X Drive 섹션이 변경되는 ArticulationBody
  • HingeJoint 범위: 새 프로퍼티 HingeJoint.extendedLimitsHingeJoint의 범위를 확대합니다. 이전에는 이 옵션 세트가 없어 범위가 [-180, 180]이었으며, 새 옵션 세트를 이용하면 범위가 [-360, 360]이 됩니다.
  • Center of Mass 및 Inertia Tensor: 이제 Center of Mass 및 Inertia Tensor 모두 Rigidbody 인스펙터(Inspector)에서 명시적으로 설정할 수 있으며 편의를 위해 직렬화됩니다.
Rigidbody with the new expandable sections that allow you to set the center of mass and inertia tensor.
확장 가능한 새 섹션에서 Center of Mass 및 Inertia Tensor를 설정할 수 있는 Rigidbody
  • Physics Debug: 이제 Physics Debug 창에 표시되는 모든 값을 복사할 수 있습니다.
You can now highlight and copy any displayed value in the Physics Debug view.
Physics Debug 뷰에 표시된 값을 하이라이트 및 복사 가능
  • ArticulationBody: 이제 임시 복사본을 스택에 할당하지 않고도 ArticulationBody 구동의 다양한 개별 프로퍼티를 설정할 수 있는 일련의 메서드가 추가되었습니다. 한 예로 ArticulationBody.SetTargetDrive는 구동의 감쇠만 설정합니다.
  • WheelCollider: 이제 새롭게 공개된 프로퍼티 WheelCollider.rotationSpeed를 사용하여 WheelCollider의 회전 속도를 가져오고 설정할 수 있습니다.
  • Inverse Dynamics: 이제 새로운 역동역학 함수 ArticulationBody.GetJointExternalForces를 사용하여 현재 작용하는 외부 힘에 대응하는 힘을 계산할 수 있습니다.

2022.2 릴리스의 물리 기능에 대해 토론하는 데 관심이 있다면 포럼에 참여해서 피드백을 공유해 주세요. 유니티는 항상 사용자의 의견을 환영합니다.

Is this article helpful for you?

Thank you for your feedback!

관련 게시물