This document is about: QUANTUM 2
SWITCH TO

Shape Config

概述

形狀設定持有一個形狀上的資訊。它可以用於輕易地在編輯器中公開設定選項,並簡化程式碼中的形狀初始化。
形狀設定可針對2D及3D - 分別是Shape2DConfigShape3DConfig

目前形狀設定的目標是與動態實體一起使用;因此,它支持的形狀類型為:

// 2D中

  • 圓形
  • 方形
  • 多邊形
  • 複合形狀(所有這些形狀的混合)

// 3D中

  • 球體
  • 長方體
  • 複合形體(也就是球體、正方體和或複合形體的混合)

以上所有形狀都相容於 形狀重疊物理碰撞器

公開形狀設定到編輯器

在您的自訂資產中包含一個Shape2DConfigShape3DConfig,將自動在編輯器中公開它。

C#

namespace Quantum
{
    public unsafe partial class WeaponSpec
    {
        public Shape3DConfig AttackShape;
        public LayerMask AttackLayers;
        public FP Damage;
        public FP KnockbackForce;
    }
}

從上述程式碼片段得到的資產,將提供以下在偵測器中公開所有形狀設定的選項:

ShapeConfig Setting of the example asset as shown in the Unity Editor
武器規格示例資產的形狀設定,如同在Unity編輯器中所顯示。

您可能已經在Entity Prototype指令碼中名為形狀2D/3D的PhysicsCollider區段中看見這個部分。

從形狀設定來建立/使用一個形狀

當使用一個形狀設定,您可以簡單地調用其CreateShape方法。這將自動地處理形狀設定資產中持有的資訊,以設定中找到的資料來建立適當的形狀及其參數。

C#

private static void Attack(in Frame f, in EntityRef entity)
{
    // A melee attack performed by using an OverlapShape on the attack area.

    var transform = f.Unsafe.GetPointer<Transform3D>(entity);
    var weapon = f.Unsafe.GetPointer<Weapon>(entity);
    var weaponSpec = f.FindAsset<WeaponSpec>(weapon->WeaponSpec.Id);

    var hits = f.Physics3D.OverlapShape(
        transform->Position,
        transform->Rotation,
        weaponSpec.AttackShape.CreateShape(f),
        weaponSpec.AttackLayers);

    // Game logic iterating over the hits.
}

當初始化一個物理碰撞器的形狀時,可以完成相同的事情。

複合形狀

一個複合形狀是一個由多種其他形狀組成的一個形狀。可用於建立一個複合形狀的形狀是在概述章節列出的形狀。

物理碰撞器及形狀重疊,與複合形狀完全相容。

目前而言,Quantum提供持續性複合形狀,也就是一個形狀指向一個堆積中的其他形狀的緩衝。這個緩衝將在幀之間一直持續,直到它被手動地處置。

建立新的複合形狀

一個複合形狀可透過簡單地調用CreateShape方法,或手動地透過Shape.CreatePersistentCompound,從一個形狀設定來建立,並且之後調用FreePersistent來處置它。這裡是一個示例,展示了如何管理生命週期,同樣的情況也適用3D形狀:

C#

    // creating a persistent compound. This does not allocate memory until you actually add shapes
    var compoundShape = Shape2D.CreatePersistentCompound();

    // adding shapes to a compound (shape1 and 2 can be of any type)
    compoundShape.Compound.AddShape(f, shape1);
    compoundShape.Compound.AddShape(f, shape2);

    (...) // Game logic

    // this compound persists until you manually dispose it
    compoundShape.Compound.FreePersistent(f);

API也提供方法,例如RemoveShapesGetShapes,及FreePersistent;檢查SDK的docs資料夾中的API文檔以取得更多關於這些方法及其他方法的資訊。

從一個現存的複合形狀來複製

您也可以透過複製一個現存的複合形狀,來建立一個新的複合形狀。

C#

// Using the exising compoundShape from the example above.

var newCompoundShape = Shape2D.CreatePersistentCompound();
compoundShape.Compound.CopyFrom(f, ref newCompoundShape);

建立一個新的複合形狀也意味著一個新的緩衝。這將需要由開發人員手動釋放,如同其他持續性複合形狀。

存取個別的形狀

如何迭代形狀的一個示例是使用GetShapes方法以取得指標緩衝,並且使用一個簡單的for迴圈,其中整數索引可用於存取所有複合中含有的Shape*
請勿超過方法傳回的count,因為它是記憶體含有的形狀指標的邊界。

C#

if (shape->Compound.GetShapes(frame, out Shape3D* shapesBuffer, out int count))
{
    for (var i = 0; i < count; i++)
    {
        Shape3D* currentShape = shapes + i;
        // do something with the shape
    }
}

複合碰撞器

一個 複合 碰撞器是一個常規碰撞器,帶有一個類型複合的形狀。

在編輯器中建立

在編輯器中,您可以在Entity Component Physics Collider 2D/3DEntity Prototype指令碼的相關區段中找到選項,來建立一個複合碰撞器。

ShapeConfig for a Compound Collider in the Entity Prototype script as shown in the Unity Editor
透過Unity編輯器中的實體原型指令碼,來建立一個複合碰撞器(球體+長方體)。

當您以一個複合形狀來建立一個碰撞器原型時,將為您處理記憶體管理,換句話說,碰撞器將有並且管理其複合形狀,而您不需要手動地處置任何事情。

在程式碼中建立

當在程式碼中建立一個碰撞器時,簡單地傳送一個複合形狀到其Create()工廠方法。當已經建立先前章節中的程式碼片段中顯示的複合形狀後,您可以以這個程式碼來替換(...),以建立一個碰撞器:

C#

    var collider = PhysicsCollider2D.Create(f, compoundShape);
    f.Set(entity, collider);

在上述提供的程式碼片段中,collider.ShapecompoundShape指向堆積中的不同的緩衝。如果您已經使用完複合形狀——換句話說,只需要建立碰撞器的話——您可以在之後立即處置它。當消除/移除時,碰撞器將在記憶體中處置其自己的副本。

關於記憶體的重要注意事項

如果一個碰撞器用作為其工廠方法Create()的一部分,一個碰撞器只建立一個複合形狀緩衝的副本。

C#

    var compoundShape = Shape2D.CreatePersistentCompound();
    compoundShape.Compound.AddShape(f, shape1);
    compoundShape.Compound.AddShape(f, shape2);

    // collider1 and collider2 each create a copy of the compoundShape buffer.
    // collider1 and collider2 will each dispose of their copy on destroy/remove.
    var collider1 = PhysicsCollider2D.Create(f, compoundShape);
    f.Set(entity1, collider1);

    var collider2 = PhysicsCollider2D.Create(f, compoundShape);
    f.Set(entity2, collider2);

    // Here we dispose of the compoundShape's buffer as it is no longer needed
    compoundShape.Compound.FreePersistent(f);

相對而言,如果您以一個常規形狀建立一個碰撞器,並且稍後設定其collider.Shape = someCompound,它將不會建立一個緩衝的副本,換句話說,collider.ShapesomeCompound將指向相同的緩衝。如果您正好有多個複合碰撞器和/或複合形狀指向相同的緩衝,這樣做可能是危險的。如果您處置其中一個,它將有效地破壞另一個到緩衝的參照。

C#

    var compoundShape = Shape2D.CreatePersistentCompound();
    compoundShape.Compound.AddShape(f, shape1);
    compoundShape.Compound.AddShape(f, shape2);

    var collider1 = PhysicsCollider2D.Create(f, default(Shape2D));
    collider1.Shape = compoundShape;
    f.Set(entity1, collider1);

    var collider2 = PhysicsCollider2D.Create(f,  Shape2D.CreateCircle(1));
    collider2.Shape = compoundShape;
    f.Set(entity2, collider2);

    // collider1.Shape, collider2.Shape and compoundShape all point to the same buffer
    // dispose of compoundShape here will break collider1 and collider2
    compoundShape.Compound.FreePersistent(f);

然而,如果您就是有意識地這樣做,這將把形狀及其記憶體管理指派給該碰撞器,從而透過將責任交給碰撞器來簡化記憶體管理,碰撞器將在消除/移除時處置它。

C#

    var compoundShape = Shape2D.CreatePersistentCompound();
    compoundShape.Compound.AddShape(f, shape1);
    compoundShape.Compound.AddShape(f, shape2);

    var collider1 = PhysicsCollider2D.Create(f, Shape2D.CreateCircle(1));
    collider1.Shape = compoundShape;
    f.Set(entity1, collider1);

    // In this instance we do not need to dispose of the compoundShape buffer because
    // collider1 already points to it and will take care of it on destroy/remove.

複合形狀查詢

完全支援廣相位及常規查詢的複合形狀查詢。行為及效能影響與執行多重查詢相同,不過結果將在同一個命中集合中傳回;

巢狀複合形狀

物理引擎透過兩個限制來支援巢狀複合形狀:

  • 一個形狀只能在其階層中的堆積中持有一個到相同緩衝的參照。新增一個已經被參照的緩衝將在偵錯模式中擲出錯誤。這是為了避免循環參照及處置時的無效指標。
  • 編輯器中不支援巢狀複合形狀(將顯示警告訊息)。這是因為Unity序列化工具限制,其要求針對形狀設定的一個更錯綜複雜的架構及下拉式選單。
Back to top