Collider and Body Components
簡介
在 Quantum 2 中,碰撞和物理行為各自擁有獨立的組件。
- 向實體添加 PhysicsCollider2D/PhysicsCollider3D 會將該實體轉換為動態障礙物或觸發器,可通過其變換進行移動。
- 添加 PhysicsBody2D/PhysicsBody3D 可使實體由物理求解器控制。
需求
Transform2D/Transform3D、PhysicsCollider2D/PhysicsCollider3D 和 PhysicsBody2D/PhysicsBody3D 組件緊密相連。因此,某些組件的運行需要其他組件作為依據。完整的依賴列表如下:
需求 | 變換 | 物理碰撞體(PhysicsCollider) | 物理體(PhysicsBody) | |
---|---|---|---|---|
組件 | ||||
變換 | ✓ | ✗ | ✗ | |
物理碰撞體(PhysicsCollider) | ✓ | ✓ | ✗ | |
物理體(PhysicsBody) | ✓ | ✓ | ✓ |
這些依賴關係相互疊加,因此要啟用 PhysicsBody,必須按以下順序向實體添加組件:
- 變換(Transform)
- 物理碰撞體(PhysicsCollider)
- 物理體(PhysicsBody)
有關碰撞回調的詳細信息,請參閱此處。
PhysicsBody 組件
向實體添加 PhysicsBody ECS 組件可使該實體被物理引擎考慮在內。注意: 使用 PhysicsBody 要求實體已具有 Transform 和 PhysicsCollider。
可以手動在代碼中創建和初始化組件,也可以通過 Unity 中的 QuantumEntityPrototype
組件進行。
C#
var entity = f.Create();
var transform = new Transform2D();
var collider = PhysicsCollider2D.Create(f, Shape2D.CreateCircle(1));
var body = PhysicsBody2D.CreateDynamic(1);
f.Set(entity, transform);
f.Set(entity, collider);
f.Set(entity, body);
3D 物理也適用相同的規則:
C#
var entity = f.Create();
var transform = Transform3D.Create();
var shape = Shape3D.CreateSphere(FP._1);
var collider = PhysicsCollider3D.Create(shape);
var body = PhysicsBody3D.CreateDynamic(FP._1);
f.Set(entity, transform);
f.Set(entity, collider);
f.Set(entity, body);
如果使用 QuantumEntityPrototype 替代方法,組件將使用 Unity 檢查器中定義的值進行初始化。

動態物體支持的形狀
PhysicsCollider3D
僅支持以下 Shape3D 用於動態實體:
- 球體
- 方塊
- 圓柱體
- 複合體(多個形狀的組合)
在編輯器中,您可以使用與 Unity 圓柱體相同的屬性(半徑和高度)來設置圓柱體形狀的屬性。但在內部,Quantum 將圓柱體定義為半徑和範圍,同時也有高度和直徑屬性。
PhysicsCollider2D
僅支持以下Shape2D
用於動態實體:
- 圓形
- 方塊
- 多邊形
- 邊緣
- 圓柱體
- 複合體(多個形狀的組合)
以下是一些可用的與圓柱體碰撞體相關的代碼片段:
C#
FP radius = FP._0_50;
FP extent = FP._1;
Shape2D shape = Shape2D.CreateCapsule(radius, extent);
// Draw the capsule
Draw.Capsule(FPVector2.Zero, shape.Capsule);
Draw.Capsule(FPVector2.Zero, extent, radius);
為清晰起見,下圖展示了 Quantum 和 Unity 的圓柱體碰撞體之間的語義差異。

質心
質心(此後簡稱為 CoM)可以在 PhysicsBody 組件上設置。質心表示相對於 Transform 組件中指定位置的偏移量。改變質心的位置可以影響施加到 PhysicsBody 上的力。

默認情況下,質心設置為 PhysicsCollider 形狀的質心。這由 PhysicsBody 配置抽屜中的Reset Center of Mass On Added
來強制執行。
注意:要自定義質心位置,必須 取消選中Reset Center of Mass On Added
標誌;否則,當 PhysicsBody 組件添加到實體時,質心將重置為碰撞體的質心。

上述配置通常用於表現為均勻密度物體(即密度均勻的物體)的實體。但是,質心和碰撞體偏移是單獨配置的。組合情況如下表所示。
PhysicsCollider 偏移 | PhysicsBody CoM | Reset Center of Mass On Added 標誌 | 結果位置 |
---|---|---|---|
默認位置 = 0, 0, 0 自定義值 = 不同於默認位置的任何位置 |
|||
默認位置 | 默認位置 | 開 / 關 | 碰撞體質心和質心位置都等於變換位置。 |
自定義值 | 默認位置 | 開 | 碰撞體質心相對於變換位置偏移,質心等於碰撞體質心位置。 |
自定義值 | 默認位置 | 關 | 碰撞體質心相對於變換位置偏移。 質心等於變換位置。 |
自定義值 | 自定義位置 | 開 | 碰撞體質心相對於變換位置偏移。 質心等於碰撞體質心位置。 |
自定義值 | 自定義位置 | 關 | 碰撞體質心相對於變換位置偏移。 質心相對於變換位置偏移。 |
複合碰撞體的質心
複合形狀的質心是所有形狀元素的質心基於其面積(2D)或體積(3D)的加權平均值的組合。
要點
總之,關於質心配置的主要要點如下。
- PhysicsCollider 偏移和 PhysicsBody 質心位置彼此不同。
- 默認情況下,PhysicsBody 配置具有
Reset Center of Mass On Added
和Reset Inertia on Added
標誌。 - 要設置自定義質心,請取消選中 PhysicsBody 配置中的
Reset Center of Mass On Added
標誌。 - 如果 PhysicsBody 配置上的
Reset Center of Mass On Added
標誌被選中,則質心在添加到實體時將自動設置為 PhysicsCollider 質心,無論編輯器中指定的質心位置如何。
施加外力
PhysicsBody API 允許手動向物體施加外力。
C#
// This is the 3D API, the 2D one is identical.
public void AddTorque(FPVector3 amount)
public void AddAngularImpulse(FPVector3 amount)
public void AddForce(FPVector3 amount, FPVector3? relativePoint = null)
public void AddLinearImpulse(FPVector3 amount, FPVector3? relativePoint = null)
// relativePoint is a vector from the body's center of mass to the point where the force is being applied, both in world space.
// If a relativePoint is provided, the resulting Torque is computed and applied.
public void AddForceAtPosition(FPVector3 force, FPVector3 position, Transform3D* transform)
public void AddImpulseAtPosition(FPVector3 force, FPVector3 position, Transform3D* transform)
// Applies the force/impulse at the position specified while taking into account the CoM.
可以通過施加以下力來影響 PhysicsBody 的角動量和線動量:
- 力(forces);或
- 衝量(impulses)。
雖然它們相似,但有一個關鍵區別:力 是在一段時間內施加的,而 衝量 是即時的。可以這樣理解它們:
- 力 = 每幀時間(deltatime)的力
- 衝量 = 每幀的力
注意: 在 Quantum 中,幀時間是固定的,取決於 Simulation Config 資產中設置的模擬速率。
無論模擬速率如何,衝量 都會產生相同的效果。但是,力 取決於模擬速率 —— 這意味著在模擬速率為 30 時向物體施加 1 的力向量,當將模擬速率提高到 60 時,幀時間將減半,因此積分力也將減半。
一般來說,當需要進行即時的瞬間變化時,建議使用 衝量;而當需要持續、逐漸地或在較長時間內施加時,則應使用 力。
初始化組件
要將 PhysicsBody 初始化為動態或運動學物體,請使用相應的創建函數。這些方法可通過 PhysicsBody2D
和 PhysicsBody3D
類訪問,例如:
- PhysicsBody3D.CreateDynamic
- PhysicsBody3D.CreateKinematic
形狀配置(ShapeConfigs)
要通過數據驅動設計初始化 PhysicsCollider 和 PhysicsBody,請使用 ShapeConfig 類型(Shape2DConfig 和 Shape3DConfig)。這些結構體可以作為屬性添加到任何 Quantum 數據資產中,可從 Unity 編輯(用於形狀、大小等)。
C#
// data asset containing a shape config property
partial class CharacterSpec {
// this will be edited from Unity
public Shape2DConfig Shape2D;
public Shape3DConfig Shape3D;
public FP Mass;
}
初始化物體時,我們使用形狀配置而不是直接使用形狀:
C#
// instantiating a player entity from the Frame object
var playerPrototype = f.FindAsset<EntityPrototype>(PLAYER_PROTOTYPE_PATH);
var playerEntity = playerPrototype.Container.CreateEntity(f);
var playerSpec = f.FindAsset<CharacterSpec>("PlayerSpec");
var transform = Transform2D.Create();
var collider = PhysicsCollider2D.Create(playerSpec.Shape2D.CreateShape(f));
var body = PhysicsBody2D.CreateKinematic(playerSpec.Mass);
// or the 3D equivalent:
var transform = Transform3D.Create();
var collider = PhysicsCollider3D.Create(playerSpec.Shape3D.CreateShape())
var body = PhysicsBody3D.CreateKinematic(playerSpec.Mass);
// Set the component data
f.Set(playerEntity, transform);
f.Set(playerEntity, collider);
f.Set(playerEntity, body);
啟用物理回調
實體可以有一組與之關聯的物理回調。這些可以通過代碼或在 Quantum Entity Prototype 的 PhysicsCollider 組件中啟用。

有關如何在代碼中設置物理回調以及如何 實現 相應的 信號,請參閱物理手冊中的回調部分。
運動學(Kinematic)
物理實體有 4 種不同的運動學樣行為方式:
僅 有一個
PhysicsCollider
組件。在這種情況下,實體沒有 PhysicsBody 組件;即沒有質量、阻力、力 / 扭矩積分等。可以隨意操縱實體變換,但是,當與動態物體碰撞時,碰撞衝量的求解就好像該實體是靜止的(線性和角速度為零)。禁用
PhysicsBody
組件。當將 PhysicsBody 上的IsEnabled
屬性設置為 false 時,物理引擎將以與要點 1 相同的方式處理該實體 —— 即視為僅有碰撞體組件。不積分力或速度。這適用於物體 臨時 表現為靜止實體,並在稍後重新啟用時保留其配置(質量、阻力係數等)的情況。將
PhysicsBody
組件 上的IsKinematic
屬性 設置 為 true。在這種情況下,物理引擎不會影響 PhysicsBody 本身,但物體的線速度和角速度在解決碰撞時仍會影響 其他物體。使用此設置來控制實體移動,而不是讓物理引擎來控制,要知道可能需要手動移動實體和控制其物體的速度,同時仍讓其他動態物體對其做出反應。使用
CreateKinematic
初始化PhysicsBody
。如果物體在整個生命周期內預期表現為運動學的,只需將其創建為運動學物體。這將使 PhysicsBody 從一開始就像要點 3 中那樣運行。如果物體最終需要變為動態的,請使用CreateDynamic
方法創建一個新的物體,並設置IsKinematic = true
。隨時可以無縫地將 IsKinematic 設置為 true/false 以及將 PhysiscBody 組件重新初始化為動態 / 運動學。
PhysicsCollider 組件
禁用 / 啟用組件
PhysicsCollider
組件配備了 Enabled
屬性。當將此屬性設置為 false
時,帶有 PhysicsCollider
的實體將在 PhysicsSystem
中被忽略。
由於 PhysicsBody
需要一個 活動的 PhysicsCollider
,因此它也將被有效地禁用。
在運行時更改形狀
可以在初始化後更改 PhysicsCollider 的形狀。
C#
var collider = f.Get<PhysicsCollider3D>(entity);
collider.Shape = myNewShape;
f.Set(entity, collider);
首次添加 PhysicsBody 時,它會根據 PhysicsCollider 的形狀計算慣性和質心。因此,建議在更改碰撞體形狀後調用 ResetInertia
和ResetCenterOfMass
。
C#
// following the snippet above
var body = f.Get<PhysicsBody3D>(entity);
body.ResetCenterOfMass(f, entity); // Needs to be called first
body.ResetInertia(f, entity); // Needs to be called second
f.Set(entity, body);
特別是當舊形狀和 / 或新形狀存在以下任何一種情況時,需要調用ResetCenterOfMass
:
- 形狀有位置偏移
- 形狀是複合形狀
- 質心有偏移