This document is about: QUANTUM 2
SWITCH TO

Collider and Body Components

概述

在Quantum 2中碰撞及物理行為各自有它們自己的元件。

  • 新增一個物理碰撞器2D/物理碰撞器3D到一個實體,將實體轉換成一個動態障礙物或觸發,其可透過它的轉換被移動。
  • 新增一個物理主體2D/物理主體3D,允許實體被物理求解所控制。

要求

轉換2D/轉換3D、物理碰撞器2D/物理碰撞器3D及物理主體2D/物理主體3D元件緊密交織在一起。其中一些是其它功能運作所需。完整的相依性清單如下:

要求 轉換 物理碰撞器 物理主體
元件
轉換 ✓ ✗ ✗
物理碰撞器 ✓ ✓ ✗
物理主體 ✓ ✓ ✓

這些相依性組建在另一者之上,因此如果您希望啟用一個物理主體,您需要以下列順序新增元件到一個實體:

  1. 轉換
  2. 物理碰撞器
  3. 物理主體

物理主體元件

新增 物理主體 ECS元件到一個實體,將使物理引擎能夠考慮這個實體。請注意: 使用一個 物理主體 需要實體已經有一個 轉換 及一個 物理碰撞器。

您可以透過手動地在程式碼中,或是透過Unity中的實體原型元件,來建立及初始化元件。

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);

在實體原型方法的情形,元件將以它們已儲存的值被初始化。

透過Unity編輯器來調整一個實體原型的物理屬性。
透過Unity編輯器來調整一個實體原型的物理屬性。

針對動態實體,物理碰撞器3D支援只支援以下形狀3D:

  • 球狀
  • 盒狀

質量中心

質量中心,以下簡稱 CoM,可在物理主體元件上被設定。CoM代表一個相對於轉換元件中指定的位置的位移。更改CoM的位置允許影響適用於物理主體的力的適用方式。

動畫示例,展示各種CoM如何影響同樣的物理主體。
動畫示例,展示各種CoM如何影響同樣的物理主體。

預設下,CoM設定為物理碰撞器形狀的質量中心。這是由物理主體設定下拉式選單中的Reset Center of Mass On Added來執行。

請注意:為了自訂CoM位置,您 必須 取消勾選Reset Center of Mass On Added旗標;不然當物理主體元件被新增到實體時,CoM將被重設為碰撞器的質量中心。

在Unity編輯器中檢視的物理主體設定中的預設旗標。
在Unity編輯器中檢視的物理主體設定中的預設旗標。

上述設定常用於一個表現為均勻密度主體的實體,也就是具有均勻密度的主體。然而,CoM及碰撞器位移被分別設定。下表說明各個組合。

物理碰撞器位移 物理主體CoM 在已新增的旗標上重設質量中心 結果位置
預設位置 = 0, 0, 0
自訂值 = 任何不同於預設位置的位置
預設位置 預設位置 開/關 碰撞器質量中心及CoM位置是相等於 轉換位置。
自訂值 預設位置 開 碰撞器質量中心是來自轉換的位移,並且CoM是相等於碰撞器質量中心位置。
自訂值 預設位置 關 碰撞器質量中心是來自轉換位置的位移。
CoM是相等於轉換位置。
自訂值 自訂位置 開 碰撞器質量中心是來自轉換位置的位移。
CoM是相等於碰撞器質量中心位置。
自訂值 自訂位置 關 碰撞器質量中心是來自轉換位置的位移。
CoM是來自轉換位置的位移。

複合碰撞器CoM

複合形狀的CoM是基於其所有形狀的元素的面積(2D)或體積(3D)的質量中心的加權平均值的組合。

關鍵點

總結而言,關於CoM設定,以下是您需要記得的主要重點。

  1. 物理碰撞器位移及物理主體CoM位置是有別於彼此。
  2. 預設下,物理主體設定有旗標Reset Center of Mass On Added及Reset Inertia on Added。
  3. 為了設定一個自訂CoM,在物理主體設定中取消勾選Reset Center of Mass On Added旗標。
  4. 如果Reset Center of Mass On Added旗標在物理主體設定上已勾選,CoM將在其被新增到實體時被自動設定為物理碰撞器質量中心——無論編輯器中指定的CoM位置為何。

應用外部力

物理主體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.

正如您可以從API所收集,物理主體的角動量及線性動量可能會受到以下應用的影響:

  • 力;或
  • 脈衝。

雖然它們很相似,有一個關鍵的不同; 力 應用於一段時間,而 脈衝 是立即性的。您可以思考成:

  • 力 = 每個差量時間的力
  • 脈衝 = 每個幀的力

請注意: 在Quantum中差量時間是固定的,並且取決於Simulation Config資產中設定的模擬率。

一個 脈衝 將產生相同的效果,無論模擬率為何。然而,一個 力 取決於模擬率——這意味著在一個30的模擬率下應用一個1的力向量到一個主體,如果您增加模擬率到60,則差量時間將為一半,並且因此已整合的力也將減半。

一般而言,當希望發生一個準時的及立即的更改時,建議使用一個 脈衝;而一個 力 則應該用於持續性、漸進性,或應用於較長時間的情形。

初始化元件

為了初始化一個 物理主體 為一個動態或運動主體,您可以使用它們相應的建立函數。這些方法可透過PhysicsBody2D及PhysicsBody3D層級存取,例如:

  • PhysicsBody3D.CreateDynamic
  • PhysicsBody3D.CreateKinematic

形狀設定

為了透過由資料驅動的設計來初始化物理碰撞器及物理主體,您可以使用 形狀設定 類型(形狀2D設定,及形狀3D設定)。這些架構可被新增為一個屬性,到任何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);

啟用物理回調

一個實體可以有一個與它關聯的物理回調的集。這些可以透過程式碼,或在 實體原型 的 物理碰撞器 元件中被啟用。

透過Unity編輯器中的實體原型的物理屬性來設定物理回調。
透過Unity編輯器中的實體原型的物理屬性來設定物理回調。

如需取得如何以程式碼設定物理回調及 執行 它們相應的 信號 的資訊,請參照物理操作手冊中的 回調 條目。

運動學

在Quantum v2中,有4個不同的方式讓一個物理實體有運動學上的行為:

  1. 透過 只 有一個PhysicsCollider 元件。在這種情況下,實體沒有一個 物理主體 元件;換句話說,沒有質量、拖曳、力/扭力整合等等...。您可以自由操控實體轉換,然而,當碰撞動態主體時,碰撞脈衝被解決的方式,就是實體如同靜止一樣(線性速度及角速度為0)。

  2. 透過 停用 PhysicsBody 元件。如果您在一個 物理主體 上設定IsEnabled屬性為 偽,則物理引擎將以與第1點所示相同的方式處理實體——也就是只有一個碰撞器元件。沒有力或速度被整合。如果您希望主體的行為在您稍後重新啟用它之前 暫時地 類似於一個靜止實體及其設定(質量、拖曳力係數等等),這是合適的。

  3. 透過在一個PhysicsBody 元件 上 設定 IsKinematic屬性為 真。在這種情況下,物理引擎將不會移動影響 物理主體 本身,但當處理碰撞時,主體的線性速度及角速度將仍然影響 其他主體。如果您希望控制實體移動而非讓物理引擎控制,並且知道您負責手動移動一個實體並且控制一個主體的速度,同時仍然讓其他動態主體回應它,請使用這個方法。

  4. 透過以CreateKinematic來 初始化 PhysicsBody。如果在主體的完整生命週期中期待主體行為是運動學的,您可以簡單地建立它為一個運動學的主體。這將從一開始就讓 物理主體 行為類似於3之中的行為。如果主體最終需要成為動態主體,您可以簡單地透過CreateDynamic方法建立一個新的主體,並且設定IsKinematic = true。設定 是運動學 為真/偽,並且可以在任何時間無縫地重新初始化 物理主體 元件為動態/運動學。

物理碰撞器元件

停用/啟用元件

從Quantum 2.1開始,PhysicsCollider元件配備有一個Enabled屬性。當設定這個屬性為false,在PhysicsSystem中,有著PhysicsCollider的實體將被忽略。

因為PhysicsBody需要一個 啟用的 PhysicsCollider,它也將有效地被停用。

在運行階段改變形狀

可以在初始化 物理碰撞器 之後改變其形狀。

C#

var collider = f.Get<PhysicsCollider3D>(entity);
collider.Shape = myNewShape;
f.Set(entity, collider);

當一個 物理主體 第一次被新增,它基於物理碰撞器的形狀來計算慣性及CoM。因此建議在改變碰撞器的形狀後調用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() 必須被 首先調用,然後才是ResetInertia()。

如果針對舊的和/或新的形狀,任何下列事項為真,則ResetCenterOfMass特別需要被調用:

  • 形狀有一個位置位移
  • 形狀是一個複合形狀
  • 質量中心有一個位移
Back to top