翻譯自: http://tsubakit1.hateblo.jp/ 此人是日本Unity的開發者, 經常分享Unity最新的技術。
新的物理系統是什麼?
Unity Physics是在ECS上運行物理的附加功能。這個物理操作並不完全是Unity過去使用的過去和安全的PhysX,而是使用C#完全重建的物理操作。
物理學的作用如下。
- 搜索空間以進行碰撞等(接觸判斷,射線判斷)
- 實際上移動物體(重力,彈跳,摩擦等)
似乎可以使用Unity Physics和Havok Plugin切換內部行爲,以便像以前那樣使用狀態進行物理操作。Havok插件適用於管理複雜狀態。Havok插件尚未發佈。
目前基於PhysX的Collider(舊的物理系統)和Unity Physics Collider (新的物理系統) 沒有任何聯繫。使用Unity Physics時,所有其他碰撞器都需要轉換爲Unity Physics。
事前準備
介紹環境就是
- Unity 2019.1f2
- Unity Physics preview1 0.0.2
- Hybrid Renderer preview10 0.0.1
暫時準備場景
如果是舊的物理, 球體上添加剛體 會向下面的圖一樣滾下斜坡
遷移到Unity Physics
Convert To Entity
添加到Spherer 。Convert To Entity
添加到Plane
這個球與平面物體 從遊戲物體轉換成基於ECS-Unity Physics 。
轉換後,它已轉換爲某些ComponentData,如下所示。請注意,在使用實體時,您需要引用下面的組件,而不是Rigidbody 。
加載一些東西,很多碰撞判斷
所以 將序列化作爲子場景。
- 從“現在準備場景”開始
- 選擇Spherer和Plane並右鍵單擊
- 從Selection中選擇New SubScene
- 按SubScene 組件上的 Close
這會將舞臺上的GameObject轉換爲實體,這樣您就可以在不插入的情況下加載反序列化。
我想使用新添加的設置
Unity Physics有一個使用SubScene和ConvertToEntity從GameObject的RigidObject轉換的流程,但也有自己的組件。
首先,○○碰撞系統已將PhysicsShape
集成到所有系統中。
Rigidbody `PhysicsBody
將是。
視頻介紹: https://www.youtube.com/watch?v=yuqM-Z-NauU
使用Unity Physics做碰撞檢測
在Unity的物理(GameObject使用PhysX)中,您可以設置OnCollisionEnter和OnTriggerEnter,但UnityPhysics目前僅提供低級API,這需要更加繁瑣的處理。
使用環境
- Unity 2019.1f2
- Unity Physics preview1 0.0.2
設置
要接收事件,您需要使用Collider
轉化爲PhysicsShape
。最重要的是PhysicsShape > Advance > Raises Collision Event
。
當被檢查實體與另一個對象接觸時,將發出一個事件。之後,我們將準備一個系統來檢查已觸發事件的內容。
首先,按系統執行順序StepPhysicsWorld
執行。
[UpdateAfter(typeof(StepPhysicsWorld))] public class ItemGetSystem: ComponentSystem {
接下來,用於接收 碰撞事件,BuildPhysicsWorld 和
StepPhysicsWorld
將提供。
private BuildPhysicsWorld buildPhysicsWorldSystem; private StepPhysicsWorld stepPhysicsWorldSystem; protected override void OnCreate() { buildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>(); stepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>(); }
它是處理實際內容的部分。
buildPhysicsWorldSystem
從中獲取PhysicsWorld。這包括目前所有碰撞者的座標。
類似的stepPhysicsWorldSystem
從中來獲得TriggerEvents
。在此存儲由引發碰撞事件啓用的對象發出的事件。
您所要做的就是讓對象與EventTrigger鍵接觸並處理事件。
protected override void OnUpdate() { var physicsWorld = buildPhysicsWorldSystem.PhysicsWorld; var triggerEvents = stepPhysicsWorldSystem.Simulation.TriggerEvents; var items = GetComponentDataFromEntity<ItemTag>(true); foreach (var triggerEvent in triggerEvents) { // PhysicsWorld包含一個適用於所有物理操作的實體。 // //在triggerEvents中,爲“引發碰撞事件”Raises Collision Event啓用的對象存儲觸摸事件 //如果清洗了TriggerEvent的內容,則可以進行觸摸判斷 var bodyA = physicsWorld.Bodies[triggerEvent.BodyIndices.BodyAIndex]; var bodyB = physicsWorld.Bodies[triggerEvent.BodyIndices.BodyBIndex]; Process(bodyA.Entity, items); Process(bodyB.Entity, items); } }
全文代碼在這裏
using Unity.Entities;
using Unity.Physics.Systems;
[UpdateAfter(typeof(StepPhysicsWorld))]
public class ItemGetSystem: ComponentSystem
{
private BuildPhysicsWorld buildPhysicsWorldSystem;
private StepPhysicsWorld stepPhysicsWorldSystem;
protected override void OnCreate()
{
buildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
stepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>();
}
protected override void OnUpdate()
{
var physicsWorld = buildPhysicsWorldSystem.PhysicsWorld;
var triggerEvents = stepPhysicsWorldSystem.Simulation.TriggerEvents;
var items = GetComponentDataFromEntity<ItemTag>(true);
foreach (var triggerEvent in triggerEvents)
{
// PhysicsWorld包含一個適用於所有物理操作的實體。
// //在triggerEvents中,爲“引發碰撞事件”Raises Collision Event啓用的對象存儲觸摸事件
//如果清洗了TriggerEvent的內容,則可以進行觸摸判斷
var bodyA = physicsWorld.Bodies[triggerEvent.BodyIndices.BodyAIndex];
var bodyB = physicsWorld.Bodies[triggerEvent.BodyIndices.BodyBIndex];
Process(bodyA.Entity, items);
Process(bodyB.Entity, items);
}
}
void Process(Entity entity, ComponentDataFromEntity<ItemTag> items)
{
if( items.Exists(entity))
{
PostUpdateCommands.DestroyEntity(entity);
UnityEngine.Debug.Log("you get item!");
}
}
}
應該注意的是,Unity Physics沒有狀態,因此似乎不能採取諸如“碰撞開始”,“ 碰撞中”和“ 碰撞結束”之類的事件。
如果只想在特定對象之間執行碰撞事件,則可以確定在ComponentDataFromEntity中是否具有特定組件,如上面的代碼中所示,或者Custom Flag
通過設置它BodyA.CustomData
。
如果您不想簡單地觸摸,最好調整碰撞濾波器。這裏的界面是我希望你再做一點的地方。
我想使用JobSystem
我嘗試使用JobSystem運行上述過程。
關鍵是要設置處理依賴性。UnityPhysics使用ECS但不適用於ECS,因此它不會自動解決處理依賴性。你需要從系統中帶來它。
inputDeps = JobHandle.CombineDependencies(
inputDeps,
buildPhysicsWorldSystem.FinalJobHandle,
stepPhysicsWorldSystem.FinalSimulationJobHandle);
整個文本看起來像這樣。
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Systems;
[UpdateAfter(typeof(StepPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
public class ItemGetSystem : JobComponentSystem
{
BuildPhysicsWorld buildPhysicsWorldSystem;
StepPhysicsWorld stepPhysicsWorldSystem;
EntityCommandBufferSystem bufferSystem;
protected override void OnCreate()
{
buildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
stepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>();
bufferSystem = World.GetOrCreateSystem<BeginSimulationEntityCommandBufferSystem>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
inputDeps = JobHandle.CombineDependencies(
inputDeps,
buildPhysicsWorldSystem.FinalJobHandle,
stepPhysicsWorldSystem.FinalSimulationJobHandle);
inputDeps = new HitAndDestroyJob {
World = buildPhysicsWorldSystem.PhysicsWorld,
TriggerEvents = stepPhysicsWorldSystem.Simulation.TriggerEvents,
items = GetComponentDataFromEntity<ItemTag>(true),
commandBuffer = bufferSystem.CreateCommandBuffer(),
}.Schedule(1, 1, inputDeps);
bufferSystem.AddJobHandleForProducer(inputDeps);
return inputDeps;
}
struct HitAndDestroyJob : IJobParallelFor
{
[ReadOnly] public PhysicsWorld World;
[ReadOnly] public TriggerEvents TriggerEvents;
[ReadOnly] public ComponentDataFromEntity<ItemTag> items;
[ReadOnly] public EntityCommandBuffer commandBuffer;
public void Execute(int index)
{
foreach (var triggerEvent in TriggerEvents)
{
GetItem(World.Bodies[triggerEvent.BodyIndices.BodyAIndex].Entity);
GetItem(World.Bodies[triggerEvent.BodyIndices.BodyBIndex].Entity);
}
}
void GetItem(Entity entity)
{
if (items.Exists(entity) == false)
return;
commandBuffer.DestroyEntity(entity);
UnityEngine.Debug.Log("you get item!");
}
}
}