Shape Config
概述
形狀設定持有一個形狀上的資訊。它可以用於輕易地在編輯器中公開設定選項,並簡化程式碼中的形狀初始化。
形狀設定可針對2D及3D - 分別是Shape2DConfig
及Shape3DConfig
。
目前形狀設定的目標是與動態實體一起使用;因此,它支持的形狀類型為:
// 2D中
- 圓形
- 方形
- 多邊形
- 邊
- 複合形狀(所有這些形狀的混合)
// 3D中
- 球體
- 長方體
- 複合形體(也就是球體、正方體和或複合形體的混合)
以上所有形狀都相容於 形狀重疊 及 物理碰撞器。
公開形狀設定到編輯器
在您的自訂資產中包含一個Shape2DConfig
或Shape3DConfig
,將自動在編輯器中公開它。
C#
namespace Quantum
{
public unsafe partial class WeaponSpec
{
public Shape3DConfig AttackShape;
public LayerMask AttackLayers;
public FP Damage;
public FP KnockbackForce;
}
}
從上述程式碼片段得到的資產,將提供以下在偵測器中公開所有形狀設定的選項:
您可能已經在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也提供方法,例如RemoveShapes
、GetShapes
,及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/3D
及Entity Prototype
指令碼的相關區段中找到選項,來建立一個複合碰撞器。
當您以一個複合形狀來建立一個碰撞器原型時,將為您處理記憶體管理,換句話說,碰撞器將有並且管理其複合形狀,而您不需要手動地處置任何事情。
在程式碼中建立
當在程式碼中建立一個碰撞器時,簡單地傳送一個複合形狀到其Create()
工廠方法。當已經建立先前章節中的程式碼片段中顯示的複合形狀後,您可以以這個程式碼來替換(...)
,以建立一個碰撞器:
C#
var collider = PhysicsCollider2D.Create(f, compoundShape);
f.Set(entity, collider);
在上述提供的程式碼片段中,collider.Shape
及compoundShape
指向堆積中的不同的緩衝。如果您已經使用完複合形狀——換句話說,只需要建立碰撞器的話——您可以在之後立即處置它。當消除/移除時,碰撞器將在記憶體中處置其自己的副本。
關於記憶體的重要注意事項
如果一個碰撞器用作為其工廠方法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.Shape
及someCompound
將指向相同的緩衝。如果您正好有多個複合碰撞器和/或複合形狀指向相同的緩衝,這樣做可能是危險的。如果您處置其中一個,它將有效地破壞另一個到緩衝的參照。
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序列化工具限制,其要求針對形狀設定的一個更錯綜複雜的架構及下拉式選單。