DOTS – Unity Physics 101 (1)

https://docs.google.com/document/d/1nHJoDBetbrmvO-KsOJ2S_p0tJI2UzRrp6T3oZSPoyg8/edit?tab=t.0#heading=h.hjbnnw9w6v0u

게임 물리의 기본 개념을 설명하고, Unity Physics API의 필수 사항들을 다룬 후, 이를 바탕으로 몇 가지 간단한 예제를 통해 기본적인 내용을 설명

물리 엔진이 하는 일

Unity Physics 패키지에 대해 구체적으로 설명하기 전 물리 엔진이 일반적으로 수행하는 일과 어떻게 작동하는 지에 대해 먼저 알아야 한다.

모든 업데이트마다 물리 엔진은 아래와 같은 네 가지 주요 단계를 순차적으로 수행한다.

  1. 효율적인 “교차 테스트”를 위한 공간 데이터 구조 구축:
    교차 테스트는 두 물리 객체의 기하학(두 물체가 부딪히거나 겹쳤는지)을 확인하는 과정
  2. 충돌 감지 및 접촉 지점에서 제약 조건 생성:
    모든 겹치거나 닿은 물리 객체들에 대해 충돌을 감지하고, 접촉 지점에서 제약 조건을 생성합니다.
  3. Physics “Solver” 실행:
    제약 조건과 물체의 질량, 중력, 마찰 등의 다른 여러 요소를 바탕으로 물리 객체의 속도를 업데이트합니다.
  4. 물리 객체 이동:
    새로 계산된 속도에 따라 물체를 이동시킵니다.

게임 코드에서는 물리 엔진이 구축한 공간 데이터 구조를 여러 게임 로직에도 사용할 수 있습니다.

예를 들어, 총이 발사될 때 게임 코드에서는 이 공간 구조를 조회하여 총알이 날아가는 경로상에 무엇이 닿을지를 결정할 수 있습니다.

참고: 각 프레임 간의 델타 시간이 자주 변하고, 물리 시뮬레이션이 렌더링이나 게임 시뮬레이션과 같은 비율로 업데이트되어야 하는 것은 아니기 때문에

물리 시뮬레이션은 고정된 업데이트 비율로 업데이트되는 경우가 많습니다.

이는 각 프레임마다 물리 업데이트를 0번 이상 수행하여 시간에 따른 평균 비율을 근사하는 방식으로 구현됩니다.

예를 들어, 한 프레임은 물리 업데이트가 0번일 수 있고, 그 다음 프레임은 3번, 그다음은 1번 등으로 업데이트되며, 시간이 지남에 따라 목표하는 물리 업데이트 비율을 맞추게 됩니다.

Rigidbodies (강체)

대부분의 게임 물리 엔진에서 물리 객체는 일반적으로 강체(즉, 고정된 질량을 가진 물체로 변형되지 않고 압축되거나 휘어지지 않는 객체)입니다.

이는 고무와 같은 연성체, 액체, 기체, 모래와 같은 입자들을 제외한 객체들입니다.

참고: 로프, 철사, 코드, 천 등은 연성체처럼 보이지만 사실은 제약 조건으로 연결된 강체 세그먼트로 근사화할 수 있습니다.

하지만 이러한 객체들은 효율성과 정확성을 위해 별도의 특별한 솔루션이 사용됩니다.

참고: 일부 강체 시뮬레이션에서는 물체가 파괴되고 부서지는 것을 지원하여, 물체가 파손되거나 부서지도록 만들 수 있습니다.

일반적으로 각 강체 객체에는 다음과 같은 요소들이 포함됩니다:

  • position / 위치
  • orientation / 회전
  • collider (the geometry used in collision detection) / 콜라이더 (충돌을 감지하는 기하학)
  • linear velocity (direction and speed of travel) / 선형 속도 (이동 방향과 속도)
  • angular velocity (direction and speed of rotation) / 각속도 (회전 방향과 속도)
  • mass / 질량
  • mass distribution (inertia tensor: the rotational semi-equivalent of mass) / 질량 분포 (관성 텐서: 회전에 대한 질량의 반영)
  • center of mass (a point, usually inside the object) / 질량의 중심 (Center of Mass)

..그리고 기타 선택적 요소들:

  • linear and angular damping (decay of velocities) / 선형 및 각속도 감쇠 (속도 감소)
  • gravity (per-object override of the global gravity) / 중력 (전역 중력에 대한 객체별 오버라이드)
  • friction coefficient / 마찰 계수
  • restitution (bounciness) / 복원력 (반발력)
  • collision filters / 충돌 필터

Colliders (콜라이더)

Unity Physics에서 지원하는 콜라이더 형태는 다음과 같습니다:

  • 박스(Box): 길이, 높이, 너비로 정의된 직사각형.
  • 구(Sphere): 반지름으로 정의된 구.
  • 캡슐(Capsule): 끝이 둥근 실린더로, 내부 선분과 반지름으로 정의됨.
  • 실린더(Cylinder): 높이와 반지름으로 정의된 실린더.
  • 삼각형/쿼드(Triangle/Quad): 3개 또는 4개의 동평면 꼭짓점으로 정의된 삼각형 또는 사각형.
  • 볼록 다면체(Convex Hull): 3D 점 집합으로 정의된 임의의 볼록 다면체.
  • 메시(Mesh): 삼각형과 쿼드로 구성된 메시.
  • 복합체(Compound): 여러 개의 콜라이더 형태로 구성된 복합체.
  • 지형(Terrain): 높이 샘플의 균일한 그리드.
https://www.reddit.com/r/Unity3D/comments/1d2b6dw/gamedev_tip_simple_colliders_tend_to_be_much_more/?rdt=41407

메시 콜라이더는 원시 콜라이더(구, 박스 등)에 비해 계산 비용이 훨씬 큽니다.

볼록 다면체 콜라이더도 원시 콜라이더보다는 계산 비용이 더 비쌉니다.

그럼에도 불구하고 메시 콜라이더보다는 훨씬 저렴합니다.

메시 콜라이더와 볼록 다면체 콜라이더의 비용은 기하학적 복잡성에 따라 증가합니다.

https://docs.unity3d.com/kr/2023.2/Manual/class-CharacterController.html

게임 성능과 플레이를 최적화하기 위해, 물체의 콜라이더(충돌 기하학)는 종종 그 물체의 시각적 기하학과 다르게 설계됩니다.

예를 들어, 캐릭터의 애니메이션 모델을 충돌 감지에 사용하면 성능이 저하되고, 캐릭터가 이동할 때 환경에 쉽게 걸릴 수 있습니다.

따라서 애니메이션 캐릭터는 캡슐과 같은 단순한 형태의 콜라이더를 사용하여 충돌을 처리하고 성능을 최적화합니다.

이렇게 하면 게임의 전반적인 퍼포먼스와 플레이 경험을 개선할 수 있습니다.

참고: 일부 게임에서는 특정 용도를 위해 캐릭터에 대한 정확한 충돌을 원할 수 있습니다.

예를 들어, 총알과의 히트 감지를 위해 캐릭터에 대한 정확한 충돌을 처리해야 하는 경우입니다.

이럴 경우 캐릭터 움직임에는 간단한 콜라이더를 사용하고, 총알과의 충돌만 처리할 수 있는 더 정밀한 두 번째, 보이지 않는 콜라이더를 사용하여 충돌을 처리합니다.

이러한 설정은 충돌 필터를 사용하는 일반적인 예입니다.

Compound colliders

https://tsubakit1.hateblo.jp/entry/2017/02/22/230100

여러 개의 콜라이더로 구성된 하나의 논리적 콜라이더입니다.

결합된 결과 형태는 반드시 볼록(Convex)일 필요 없으며, 각 개별 콜라이더는 서로 닿거나 교차할 필요도 없습니다.

Compound Collider는 다음과 같은 경우에 유용합니다:

  • 복잡한 콜라이더 형태를 원하면서도 메쉬 콜라이더보다 더 저렴한 충돌 계산을 원할 때
    여러 개의 원시 콜라이더(예: 박스, 구 등)를 조합하여 복잡한 형태의 콜라이더를 만들 수 있습니다.
    이렇게 하면 메쉬 콜라이더의 높은 성능 비용을 피하면서도 복잡한 충돌 처리를 할 수 있습니다.
  • 물체의 여러 부분에 대해 충돌을 구별하고 싶을 때
    예를 들어, 캐릭터의 머리, 몸통 또는 다른 부위와 같은 개별적인 부분에 대해 총알과의 충돌을 구별하고자 할 때 사용할 수 있습니다.
    각 부위에 대해 개별적인 콜라이더를 사용하고, 이를 하나의 논리적 콜라이더로 결합함으로써 충돌을 구분할 수 있습니다.

Dynamic and kinematic bodies

동적 물체(Dynamic Body):
일반적인 강체 물리 객체로, 중력과 충돌에서 발생한 힘에 영향을 받는 물체를 의미합니다.
즉, 물리 엔진에서 이 물체는 다른 물체와 충돌할 때 그에 맞게 변동하는 물리적 특성을 가집니다.

키네마틱 물체(Kinematic Body):
무한한 질량을 가진 강체 물체입니다.
즉, 이 물체는 충돌이나 다른 강체와의 상호작용에 의해 자동으로 변하지 않으며, 물리적인 힘에 의해 영향을 받지 않습니다.
대신, 사용자의 코드가 이 물체의 변환(transform)과 속도를 설정하여 이동을 제어합니다.

참고: 위키백과에 따르면, “키네마틱(Kinematics)은 물체의 운동을 설명하는 물리학 및 수학의 하위 분야로, 물체들이 어떻게 움직이는지 그 원인을 고려하지 않고 기술합니다.

” 따라서 물리 엔진에서 “키네마틱”이라는 용어는 외부 힘을 자동으로 받지 않는 물체를 설명하는 데 적합합니다.

캐릭터 컨트롤러는 Kinematic Body의 중요한 사용 사례입니다.

몇몇 게임에서는Dynamic Body 캐릭터 컨트롤러를 사용하지만, 프로그래머가 이를 제어하기 어렵게 만들 수 있습니다.

프로그래머가 Dynamic Body의 위치나 속도를 직접 설정하면 물리 엔진에 의해 적용된 충돌 힘을 무시하게 되어, 객체가 다른 콜라이더를 관통하거나 바람직하지 않은 동작을 초래할 수 있습니다.

반면, kinematic 컨트롤러는 자동으로 다른 콜라이더와의 충돌을 고려하지 않기 때문에, 프로그래머가 충돌을 컨트롤러 로직에 수동으로 반영해야 합니다.

Kinematic 물체는 물체가 이동할 때 다른 물체에 영향을 주지만, 스스로는 그 충돌이나 다른 물리적 속성(예: 중력, 마찰, 감쇠 등)에 자동으로 반응하지 않도록 하려는 경우 유용합니다.

예를 들어, 엘리베이터는 다른 물체들이 그 바닥에 있을 때 영향을 미쳐야 하므로 물리 객체여야 하지만, 엘리베이터가 장애물에 걸리거나 중력에 의해 영향을 받지 않도록 하려면 Kinematic 물체로 설정하는 것이 좋습니다.

이 경우, 엘리베이터의 이동은 사용자의 코드에서 제어할 수 있습니다.

Static colliders (정적 콜라이더)

Static collidercollider를 가지고 있지만, 속도나 질량, 동적 물체의 다른 속성들은 없는 객체입니다.

일반적으로 게임 환경을 구성하는 객체들, 예를 들어 정적 소품, 바닥, 벽, 지형 등은 Static collider로 설정됩니다.

Static collider와 동적 또는 키네마틱 물체 간의 충돌에서, 정적 콜라이더는 무한한 질량을 가진 물체처럼 처리됩니다. 즉, 정적 콜라이더는 움직이지 않는 물체로 간주됩니다.

물리 엔진은 정적 콜라이더들 간의 충돌을 검사하지 않습니다.

참고: Unity Physics에서는 실행 중에 정적 콜라이더를 이동시킬 수 있지만, 이는 충돌 검사를 위한 정적 콜라이더의 경계 볼륨 계층을 재구성하는 비용이 많이 드는 작업을 발생시킵니다.

일반적으로 Static collider를 이동시키는 것은 피하는 것이 좋습니다. 만약 가끔 이동하는 콜라이더가 필요하다면, 속도가 0인 키네마틱 물체를 사용하는 것을 고려하세요.

Collision queries (충돌 쿼리)

게임 코드에서 물리 엔진에 “이 객체가 이 위치로 이동하거나 이 방향으로 움직이면 무엇을 충돌할까?” 또는 “이 총알이 이 방향으로 발사된다면 무엇을 충돌할까?”와 같은 질문을 하는 것이 종종 유용합니다.

이러한 질문들을 충돌 쿼리(collision queries)라고 합니다.

Unity Physics API는 다음과 같은 5가지 종류의 충돌 쿼리를 제공합니다:

  • 오버랩 쿼리(Overlap query): 주어진 형태와 겹치는 경계 상자가 있는 모든 콜라이더를 찾습니다.
  • 레이캐스트 쿼리(Raycast query): 주어진 레이(방향이 있는 선분)와 교차하는 모든 콜라이더를 찾습니다.
  • 콜라이더 캐스트 쿼리(Collider cast query): 주어진 선분을 따라 이동하는 형태와 교차하는 모든 콜라이더를 찾습니다. 이를 “shape cast” 또는 “sweep”이라고도 합니다.
  • 콜라이더 거리 쿼리(Collider distance query): 주어진 형태와 각 콜라이더 간의 최단 거리를 찾아, 주어진 최대 반경 내에서 이를 계산합니다.
  • 포인트 거리 쿼리(Point distance query): 주어진 점과 각 콜라이더 간의 최단 선분을 찾고, 주어진 최대 반경 내에서 이를 계산합니다.

Collision and trigger events (충돌 및 트리거 이벤트)

물리 객체들 간에 감지된 충돌에 대해, 물리 엔진은 충돌에 관한 정보를 포함한 충돌 이벤트를 생성할 수 있습니다.

이러한 이벤트를 코드에서 처리하는 것은 많은 게임 플레이 용도로 유용할 수 있습니다.

예를 들어, 키네마틱 캐릭터 컨트롤러가 충돌에 반응하도록 할 수 있습니다.

모든 충돌에 대해 이벤트를 발생시키는 것은 비용이 매우 크기 때문에,

물리 엔진은 일반적으로 이벤트를 발생시킬 객체를 사용자가 지정한 객체들만 대상으로 이벤트를 발생시킵니다.

트리거 (Trigger)

트리거는 (보통 보이지 않는) 콜라이더로, 이 콜라이더의 충돌은 제약을 생성하지 않기 때문에 다른 객체들이 트리거와 자유롭게 교차할 수 있습니다.

물리 객체와 트리거 간에 감지된 충돌에 대해, 물리 엔진은 트리거 이벤트를 생성합니다.

이 이벤트는 코드에서 읽을 수 있으며, 예를 들어 플레이어 캐릭터가 특정 지역에 들어갔을 때와 같은 발생을 감지하는 데 사용할 수 있습니다.

Collision filtering (충돌 필터링)

https://docs.unity3d.com/Manual/LayerBasedCollision.html

많은 게임 플레이 시나리오에서, 모든 물리 객체가 서로 충돌할 때마다 반드시 접촉 제약과 이벤트를 생성하지 않기를 원할 수 있습니다.

예를 들어, 게임에서 투사체장식용 파편을 통과하게 하거나, 움직이는 객체들이 서로 연결되어 있을 때 서로를 통과하도록 하고 싶을 수 있습니다.

이러한 문제를 해결하기 위해, 충돌 필터링을 사용하여 개별 객체 또는 객체 그룹이 서로 충돌할 때 접촉 제약과 이벤트를 생성할지 여부를 지정할 수 있습니다.

The broad phase and narrow phases of collision detection

어떤 물리 객체들이 서로 충돌하는지 확인하는 것은 비용이 많이 들 수 있기 때문에, 충돌 탐지는 일반적으로 두 단계로 나뉩니다:

  1. 광범위 단계 (Broad Phase):
    이 단계에서 물리 엔진은 축 정렬 경계 상자(Axis-Aligned Bounding Boxes – AABB)가 교차하는 콜라이더들을 찾습니다.
    AABB는 물체를 완전히 감싸는, 세계 축에 맞춰 정렬된 박스입니다.
  2. 좁은 단계 (Narrow Phase):
    광범위 단계에서 AABB가 교차한 객체들의 실제 콜라이더들이 충돌하는지 확인합니다.

축 정렬 경계 상자(AABB) 교차 테스트는 개별적으로 비용이 저렴하기 때문에(특히, hull 및 mesh교차 테스트와 비교했을 때), 충돌 감지를 광범위 단계와 좁은 단계로 나누면 필요한 교차 테스트 쌍의 수를 줄일 수 있습니다.

넓은 단계는 콜라이더의 AABB를 octree 또는 Bounding Volume Hierarchy (BVH)와 같은 공간 구조에 그룹화함으로써 더욱 가속화됩니다.

이를 통해 브로드 단계에서는 동일한 세계 영역에 있는 AABB 간의 교차만 확인하면 됩니다.

Unity Physics는 dynamic bodies와 kinematics를 위해 BVH를 생성하고, Static colliders를 위해 별도의 추가 BVH를 생성합니다.

Joints and motors

물리 엔진의 충돌 탐지에서 생성된 접촉 제약 외에도, 때로는 두 객체가 함께 끌어당기게 하는 등의 지속적인 제약을 수동으로 생성하고 싶을 수 있습니다.

이러한 두 객체 간의 지속적인 제약을 조인트(Joint)라고 합니다.

조인트는 구성에 따라 특정 자유도(DoF)를 제한할 수 있습니다.

예를 들어, 조인트는 두 객체가 단일 축을 중심으로만 상대 회전하도록 제한할 수 있습니다.

https://docs.unity3d.com/6000.0/Documentation/Manual/physics-articulations.html

Unity Physics는 여러 종류의 조인트를 제공합니다:

  • Ball and Socket: 여러 축을 중심으로 움직임을 허용합니다. 인간의 엉덩이와 어깨에 해당합니다.
  • Limited Hinge: 한 축을 중심으로 제한된 회전만 허용합니다. 인간의 손가락과 무릎에 해당합니다.
  • Fixed: 두 개의 강체를 고정하여 독립적으로 움직이지 않게 만듭니다.
  • Hinge: 한 축을 중심으로 자유로운 회전을 허용합니다. 회전하는 바퀴나 회전목마에 사용될 수 있습니다.
  • Prismatic: 두 객체를 한 축을 중심으로 슬라이딩 움직임에 제한합니다. 다양한 슬라이딩 문에 사용될 수 있습니다.
  • Ragdoll: 몇 가지 축에서 제한된 움직임을 허용합니다. 캐릭터 생성에 유용합니다.
  • Stiff Spring: 두 객체가 일정 거리를 유지하도록 제한합니다.

모터(Motor)는 구동 제약을 가진 조인트의 변형입니다. 이는 두 객체가 정지 상태에 있을 때에도 힘을 가하여 움직이게 만듭니다.

Unity Physics는 몇 가지 종류의 모터를 제공합니다:

  • Rotation Motor: 축을 중심으로 타겟 각도를 향해 회전하는 모터화된 힌지 조인트입니다.
  • Angular Velocity Motor: 일정한 타겟 속도로 축을 중심으로 회전하는 모터화된 힌지 조인트입니다.
  • Position Motor: 상대적인 타겟 위치로 움직이는 모터화된 프리즘 조인트입니다.
  • Linear Velocity Motor: 일정한 속도로 상대적인 타겟 위치로 이동하는 모터화된 프리즘 조인트입니다.

https://learn.unity.com/tutorial/ecsyong-mulri-havok-physics-for-unitywa-unity-physics#

Unity Physics API

Static collider entities (정적 콜라이더 엔터티)

Static collider entities는 일반적으로 움직이지 않을 것으로 예상되는 충돌 기하학를 나타냅니다.

예를 들어, 게임 환경을 구성하는 지면과 벽 등이 이에 해당합니다.

Static collider entities를 런타임에 이동시키면 정적 콜라이더 계층의 재구성이 필요하며 이는 성능에 큰 부담을 줄 수 있습니다.

따라서 Static collider는 가능하면 드물게 이동시키거나, 아예 이동시키지 않는 것이 권장됩니다.

Static collider entities는 두 가지 컴포넌트로 정의됩니다:

1. PhysicsCollider:

  • 콜라이더에 대한 핵심 정보를 포함합니다. 여기에는 다음이 포함됩니다:
    • The collider geometry 콜라이더 기하학
    • Collision filter properties 충돌 필터 속성
    • Mass distribution properties 질량 분포 속성
    • Friction properties 마찰 속성
    • Restitution (bounciness) properties 탄성(튕김) 속성

    참고: 충돌 지오메트리는 BlobAssetReference<Collider>에 저장됩니다.

    여러 엔터티의 PhysicsCollider 컴포넌트가 동일한 BlobAssetReference<Collider>를 공유할 수 있습니다.

    따라서 특정 콜라이더를 변경하면 여러 엔터티의 콜라이더에 영향을 미칠 수 있습니다.

    이를 방지하려면 각 엔터티에 고유한 콜라이더 복사본을 제공해야 합니다.

    2. PhysicsWorldIndex:

    • 이 컴포넌트는 해당 엔터티가 어떤 “물리 월드(physics world)”에 속해 있는지를 나타냅니다.
      물리 엔터티는 동일한 물리 월드에 속한 다른 물리 엔터티와만 충돌 및 상호작용을 합니다.

    참고: “물리 월드(physics world)” 개념은 일반적인 엔터티 월드(entity World)와는 다릅니다.

    엔터티 월드는 특정 엔터티와 시스템 집합을 포함하며, 다른 엔터티 월드와 논리적으로 분리됩니다.

    반면, 물리 월드는 단일 엔터티 월드 내의 일부 물리 엔터티만을 포함합니다.

    일반적으로 기본 물리 월드(0)만 사용되지만, 고급 사례에서는 추가 물리 월드가 유용할 수 있습니다.

    복합 콜라이더(Compound Collider, 여러 개의 개별 지오메트리로 구성된 콜라이더)의 경우, 다음과 같은 컴포넌트를 가질 수 있습니다:

    • PhysicsColliderKeyEntityPair: 복합 콜라이더를 구성하는 개별 콜라이더들을 참조하는 버퍼입니다.

    Rigid Body Entities (강체 엔터티)

    강체 엔터티는 물리적 특성(속도, 질량 등)을 가진 물리 바디를 나타냅니다.

    1. 동적 강체 (Dynamic Rigid Body)

    동적 Rigid Body Entities는 속도, 질량, 기타 물리적 특성을 가진 물리 객체를 의미합니다.

    2. 키네마틱 강체 (Kinematic Rigid Body)

    키네마틱 Rigid Body는 무한한 질량과 관성을 가진 동적 Rigid Body입니다.

    • 충돌로 인한 물리적 힘에 자동으로 반응하지 않습니다.
    • 캐릭터 및 차량 컨트롤러, 엘리베이터, 움직이는 플랫폼처럼 프로그래밍으로 이동하는 객체에 자주 사용됩니다.

    Rigid Body Entities의 구성 요소

    Rigid Body Entities는 콜라이더 컴포넌트 외에도 다음과 같은 추가 컴포넌트를 가질 수 있습니다:

    필수 컴포넌트:

    1. PhysicsVelocity
      • 바디의 선형 및 각속도를 나타냅니다.
    2. PhysicsMass
      • 질량, 질량 중심, 관성, 그리고 각 확장 계수(Angular Expansion Factor)를 정의합니다.
    • 참고: PhysicsMass의 선형 속도는 월드 공간(world space)에서 표현됩니다.
      각속도는 월드 공간이 아닌 PhysicsMass 변환 기준으로 표현됩니다.
      “각 확장 계수”는 강체의 AABB(Axis-Aligned Bounding Box)를 확장하여 움직임을 포함하는 체적(swept volume)을 포괄하는 정도를 결정합니다.

    선택적 컴포넌트 (추가 물리적 속성 정의):

    1. PhysicsDamping
      • 각 시뮬레이션 단계에서 속도에 감쇠를 적용합니다.
    2. PhysicsGravityFactor
      • 이 바디에 대한 전역 중력을 수정하는 중력 계수입니다.
    3. PhysicsCustomTags
      • 사용자 정의 데이터로, 이 바디와 관련된 충돌 또는 트리거 이벤트에 복사됩니다.
      • 이벤트 처리 코드에서 바디를 분류하는 데 유용합니다.
    4. PhysicsTemporalCoherenceInfo
      • 물리적 시간적 일관성 정보를 저장합니다.
    5. PhysicsTemporalCoherenceTag
      • 물리적 시간적 일관성을 식별하기 위한 태그입니다.
    6. PhysicsMassOverride
      • 엔터티를 키네마틱 또는 비키네마틱 상태로 전환할 수 있는 플래그를 포함합니다.
      • 키네마틱 강체 엔터티의 경우 기본적으로 필요하지 않지만, 상태 전환이 필요한 경우 사용됩니다.

    그래픽 관련 선택적 컴포넌트:

    1. PhysicsRenderEntity
      • 물리 객체와 그래픽 렌더링을 별개의 엔터티로 표현하려는 경우 사용됩니다.
      • 렌더링되지 않는 물리 엔터티에 대해 그래픽 표현을 담당할 엔터티를 참조로 저장합니다.
    2. PhysicsGraphicalSmoothing
      • 그래픽 표현 엔터티의 움직임을 부드럽게 처리합니다.
      • 렌더링 프레임 속도가 물리 고정 단계 속도를 초과할 경우에만 적용됩니다.
    3. PhysicsGraphicalInterpolationBuffer
      • 이전 물리 틱(physics tick)에서의 강체 상태를 저장하여 그래픽 표현의 움직임을 보간(interpolation)합니다.
      • PhysicsGraphicalSmoothing과 함께 사용하면, 가장 최근의 두 물리 시뮬레이션 틱 간의 보간을 처리하여 물리 시뮬레이션의 더 정확한 표현을 제공합니다. 다만, 1틱의 지연(latency)이 추가됩니다.

    Joints and motors

    조인트(Joint)는 두 강체 엔터티를 연결하는 제약 조건의 집합을 나타냅니다.

    모터(Motor)는 “구동” 제약 조건을 가지는 조인트의 일종으로, 두 강체에 힘(예: 회전력)을 가합니다.

    조인트 및 모터 엔터티 구성 요소

    조인트 또는 모터는 엔터티로 표현되며, 다음 두 가지 컴포넌트를 가집니다:

    1. PhysicsJoint
      • 조인트의 속성을 정의합니다.
        • BodyFrame: 두 강체에 대한 상대적인 조인트 변환을 정의합니다.
        • JointType: 조인트 유형(enum)으로, Fixed, Hinge, RotationalMotor 등이 있습니다.
        • Constraints: 적용될 제약 조건 집합입니다.
    2. PhysicsConstrainedBodyPair
      • 두 강체를 연결합니다.
        • 두 강체의 엔터티 ID(Entity ID)
        • 두 강체가 충돌 이벤트를 생성해야 하는지 여부를 나타내는 정수 값
    추가 컴포넌트 (선택 사항)

    조인트와 모터 엔터티가 복잡한 조인트 설정의 일부인 경우, 다음 컴포넌트를 포함할 수 있습니다:

    • PhysicsJointCompanion
      • 복합 조인트 설정을 구성하는 다른 조인트 엔터티를 참조하는 버퍼입니다.
    주의사항
    • 조인트와 모터는 반드시 별도의 엔터티로 만들어질 필요는 없습니다.
      • 예를 들어, PhysicsJointPhysicsConstrainedBodyPair 컴포넌트를 조인트로 연결된 두 강체 중 하나에 추가하여 조인트를 생성할 수 있습니다.
      • 중요한 점은 PhysicsJoint와 관련된 PhysicsConstrainedBodyPair(및 선택적으로 PhysicsJointCompanion)가 동일한 엔터티에 있어야 한다는 것입니다.

    Additional singleton components 추가 싱글톤 컴포넌트

    Unity Physics는 핵심 물리 기능에 접근하기 위한 두 개의 싱글톤 컴포넌트를 제공합니다:

    1. SimulationSingleton
      • 충돌, 트리거, 충격 이벤트를 처리할 때 사용되는 Simulation에 접근을 제공합니다.
    2. PhysicsWorldSingleton
      • PhysicsWorld에 접근을 제공합니다.

    Unity Physics는 이 두 컴포넌트를 포함하는 엔터티를 자동으로 생성합니다.

    추가적인 글로벌 설정 및 디버깅 싱글톤 컴포넌트

    다음 두 싱글톤 컴포넌트는 전역 물리 설정을 지정하거나 시각적 디버깅 도구를 활성화하는 데 사용됩니다:

    1. PhysicsStep
      • 물리 월드의 “스텝” 방식을 결정하는 속성을 포함합니다.
      • 이 싱글톤 인스턴스가 없으면 기본값이 사용됩니다.
    2. PhysicsDebugDisplayData
      • 충돌체의 와이어프레임과 같은 물리 디버그 시각화를 활성화할지 여부를 결정합니다.
      • 이 싱글톤 인스턴스가 없으면 기본값이 사용됩니다.

    참고: “싱글톤”은 월드 내에서 이러한 컴포넌트가 하나의 엔터티에만 추가되어야 함을 의미합니다.


    Creating physics entities in the editor

    Note: This section assumes you have basic familiarity with entity baking.

    To create physics entities in a subscene, you have three options:

    1. Use the “Built-in” physics components (the standard GameObject physics components). Because these Built-in components were designed for PhysX, they don’t neatly map to Unity Physics in all regards, but they are sufficient for most common cases.
    2. Use the physics authoring components published in the Unity Physics package samples. These authoring components were designed for Unity Physics and so map more accurately to its functionality.
    3. Make your own custom authoring components. If you study the authoring components from the package samples, you may learn enough to create your own that better fit your needs. Be warned, though, that some facets of the underlying Unity Physics component data (such as those related to joints and motors) require deep understanding of the physics engine to set up properly.

    (For simplicity, we will focus on the first option in the samples below.)

    When a GameObject with a collider component in a subscene is baked, the created entity is given the Unity.Physics components PhysicsCollider and PhysicsWorldIndex.

    When a GameObject with a RigidBody component in a subscene is baked, the created entity is given the Unity.Physics components PhysicsVelocity, PhysicsMass, and PhysicsDamping.

    Creating physics entities at runtime

    To create a static collider entity at runtime:

    1. Create an entity.
    2. Add the transform components, LocalTransform and LocalToWorld, to the entity. 
    3. Add the rendering components to the entity by calling RenderMeshUtility.AddComponents.
    4. Set the RenderBounds component with an AABB that encompasses the object.
    5. Add a PhysicsWorldIndex component to the entity. (The default value of 0 is fine if you aren’t using more than one physics world.)
    6. Add a PhysicsCollider component to the entity. To create a BlobAssetReference for the PhysicsCollider, you can use one of the convenience methods that return a collider:
      • BoxCollider.Create
      • CapsuleCollider.Create
      • CompoundCollider.Create
      • ConvexCollider.Create
      • CylinderCollider.Create
      • MeshCollider.Create 
      • PolygonCollider.CreateTriangle
      • PolygonCollider.CreateQuad
      • SphereCollider.Create
      • TerrainCollider.Create

    To create a dynamic body entity at runtime:

    1. Follow the same steps as for a static collider.
    2. Add a PhysicsVelocity component to the entity.
    3. Add a PhysicsMass component to the entity. To create the PhysicsMass value, you can call PhysicsMass.CreateDynamic or PhysicsMass.CreateKinematic

    See a full code example here.

    To create a joint or motor entity at runtime:

    1. Create an entity.
    2. Add a PhysicsWorldIndex component to the entity. The default value of 0 is usually fine (unless you are using multiple physics worlds).
    3. Add the PhysicsConstrainedBodyPair component to the entity. Set the component to reference the two body entities.
    4. Add the PhysicsJoint component. There are a number of static methods for creating a PhysicsJoint with the appropriate settings:
      • PhysicsJoint.CreateAngularVelocityMotor
      • PhysicsJoint.CreateBallAndSocket
      • PhysicsJoint.CreateFixed
      • PhysicsJoint.CreateHinge
      • PhysicsJoint.CreateLimitedDistance
      • PhysicsJoint.CreateLimitedDOF
      • PhysicsJoint.CreateLimitedHinge
      • PhysicsJoint.CreateLinearVelocityMotor
      • PhysicsJoint.CreatePositionMotor
      • PhysicsJoint.CreatePrismatic
      • PhysicsJoint.CreateRagdoll
      • PhysicsJoint.CreateRotationalMotor

    Note: Manually setting the fields of the PhysicsJoint correctly requires deep understanding of the solver and so is not recommended for most users.

    Also note that, although the Built-in (GameObject PhysX) joint MonoBehaviours can be used to bake joint entities in subscenes, a few properties of these MonoBehaviours are ignored in baking because they do not map directly to attributes of a Unity Physics joint.


    The Physics systems

    This is the hierarchy of physics-related system groups and systems (as of Unity Physics version 1.3.8):

    • Simulation System Group
      • Fixed Step Simulation Group
        • Inject Temporal Coherence Data System
        • Physics System Group
          • Sync Custom Physics Proxy System
          • Collider Blob Cleanup System
          • Before Physics System Group
            • Ensure Unique Collider System
          • Physics Initialize Group
            • Clean Physics Debug Data System_Default
            • Physics Initialize Group Internal
              • Clean Physics World Dependency Resolver
              • Physics Build World Group
                • Inject Temporal Coherence Data Last Resort System
                • Build Physics World
                • Invalidated Temporal Coherence Cleanup System
                • Integrity Check System
              • Physics Analytics System
          • Physics Simulation Group
            • Physics Simulation Picker System
            • Physics Create Body Pairs Group
              • Broadphase System
            • Physics Create Contacts Group
              • Narrowphase System
            • Physics Create Jacobians Group
              • Create Jacobians System
            • Physics Solve And Integrate Group
              • Solve and Integrate System
          • Buffer Interpolated Rigid Bodies Motion
          • Record Most Recent Fixed Time
          • Export Physics World
          • After Physics Simulation Group
            • Display Collision Events System
            • Display Trigger Events System
          • Modify Joint Limits System
          • Copy Physics Velocity to Smoothing
      • Transform System Group
        • Smooth Rigid Bodies Graphical Motion
      • Late Simulation System Group
        • Physics Debug Display Group
          • Display Body Colliders System
          • Display Broadphase Aabbs System
          • Display Collider Aabbs System_Default
          • Display Body Collider Edges_Default
          • Query Tester System
          • Display Trigger Events System
          • Display Mass Properties System
          • Display Joints System_Default
          • Display Collision Events System
          • Physics Debug Display System_Default

    Note: When using Netcode for Entities, the server puts the PhysicsSystemGroup inside the PredictedFixedStepSimulationGroup.

    The core physics update happens within each iteration of the PhysicsSystemGroup:

    1. The PhysicsInitializeGroup sets up the “physics world”. This entails copying transforms, velocities, and other physics properties from the physics body entities to Unity Physics’s internal representation of the physics simulation.
    2. The BroadphaseSystem identifies the pairs of bodies that have overlapping AABB’s.
    3. The NarrowPhaseSystem determines which of these pairs actually collide and generates contacts accordingly.
    4. The CreateJacobiansSystem creates jacobians from the contacts and joint constraints.
    5. The SolveAndIntegrateSystem solves the jacobians to update the transforms and velocities within the physics world.
    6. The ExportPhysicsWorld system copies the transforms and velocities from the physics world back to the physics body entities.

    Keep in mind that PhysicsSystemGroup is inside FixedStepSimulationGroup, which iterates 0 or more times each frame based on the fixed step rate, so 0 or more physics updates may be performed each frame.

    Note: ExportPhysicsWorld expects the rigid bodies to remain in the same chunk location as found by the PhysicsInitializeGroup, so it is not safe to make structural changes in between that would move these entities or destroy them (e.g. do not add components or remove components from these entities). In the editor and development builds, ExportPhysicsWorld performs “integrity checks” to catch such mistakes, but the checks are skipped in release builds. Also understand that, because ExportPhysicsWorld overwrites the values of the physics components, any writes you make directly to these components in between PhysicsInitializeGroup and ExportPhysicsWorld will be clobbered and effectively ignored.

    To order a system relative to the physics updates, you’ll typically use one of these attributes:

    [UpdateInGroup(typeof(AfterPhysicsSystemGroup))]: Update immediately after each physics update of the frame (if any)

    [UpdateBefore(typeof(FixedStepSimulationGroup))]: Update once in the frame before all physics updates (even if none)

    [UpdateAfter(typeof(FixedStepSimulationGroup))]:  Update once in the frame after all physics updates (even if none)

    [UpdateInGroup(typeof(BeforePhysicsSystemGroup))]: Update immediately before each physics update of the frame (if any)

    댓글 달기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

    위로 스크롤