关于Unity 2019中的新物理系统相关

翻译自: http://tsubakit1.hateblo.jp/ 此人是日本Unity的开发者, 经常分享Unity最新的技术。 

         新的物理系统是什么?

         Unity Physics是在ECS上运行物理的附加功能。这个物理操作并不完全是Unity过去使用过去和安全的PhysX,而是使用C#完全重建的物理操作。

物理学的作用如下。

  • 搜索空间以进行碰撞等(接触判断,射线判断)
  • 实际上移动物体(重力,弹跳,摩擦等)

关于Unity 2019中的新物理系统相关_第1张图片

         似乎可以使用Unity Physics和Havok Plugin切换内部行为,以便像以前那样使用状态进行物理操作。Havok插件适用于管理复杂状态。Havok插件尚未发布。

关于Unity 2019中的新物理系统相关_第2张图片

        目前基于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 2019中的新物理系统相关_第3张图片

暂时准备场景

      如果是旧的物理, 球体上添加刚体 会向下面的图一样滚下斜坡

关于Unity 2019中的新物理系统相关_第4张图片

迁移到Unity Physics

  • Convert To Entity添加到Spherer 。
  • Convert To Entity添加到Plane

这个球与平面物体  从游戏物体转换成基于ECS-Unity Physics 

关于Unity 2019中的新物理系统相关_第5张图片

关于Unity 2019中的新物理系统相关_第6张图片

转换后,它已转换为某些ComponentData,如下所示。请注意,在使用实体时,您需要引用下面的组件,而不是Rigidbody 。

关于Unity 2019中的新物理系统相关_第7张图片

加载一些东西,很多碰撞判断

  1. 加载场景
  2. 使游戏对象序列化
  3. 使组件序列化
  4. 生成ComponentData
  5. 销毁GameObject
  6. 重复转换为实体 

所以 将序列化作为子场景。

  • 从“现在准备场景”开始
  • 选择Spherer和Plane并右键单击
  • 从Selection中选择New SubScene
  • 按SubScene 组件上的  Close

这会将舞台上的GameObject转换为实体,这样您就可以在不插入的情况下加载反序列化。

关于Unity 2019中的新物理系统相关_第8张图片

我想使用新添加的设置

Unity Physics有一个使用SubScene和ConvertToEntity从GameObject的RigidObject转换的流程,但也有自己的组件。

首先,○○碰撞系统已将PhysicsShape集成到所有系统中。 

关于Unity 2019中的新物理系统相关_第9张图片

Rigidbody `PhysicsBody将是。

关于Unity 2019中的新物理系统相关_第10张图片

          视频介绍: https://www.youtube.com/watch?v=yuqM-Z-NauU   

 

 

使用Unity Physics做碰撞检测

关于Unity 2019中的新物理系统相关_第11张图片

在Unity的物理(GameObject使用PhysX)中,您可以设置OnCollisionEnter和OnTriggerEnter,但UnityPhysics目前仅提供低级API,这需要更加繁琐的处理。

 

使用环境

  • Unity 2019.1f2
  • Unity Physics preview1 0.0.2

设置

要接收事件,您需要使用Collider转化为PhysicsShape。最重要的是PhysicsShape > Advance > Raises Collision Event 

关于Unity 2019中的新物理系统相关_第12张图片

         当被检查实体与另一个对象接触时,将发出一个事件。之后,我们将准备一个系统来检查已触发事件的内容。

首先,按系统执行顺序StepPhysicsWorld执行。

[UpdateAfter(typeof(StepPhysicsWorld))]
public class ItemGetSystem: ComponentSystem
{

接下来,用于接收 碰撞事件,BuildPhysicsWorld 和 StepPhysicsWorld将提供。

    private BuildPhysicsWorld buildPhysicsWorldSystem;
    private StepPhysicsWorld stepPhysicsWorldSystem;

    protected override void OnCreate()
    {
        buildPhysicsWorldSystem = World.GetOrCreateSystem();
        stepPhysicsWorldSystem = World.GetOrCreateSystem();
    }

它是处理实际内容的部分。

buildPhysicsWorldSystem从中获取PhysicsWorld。这包括目前所有碰撞者的坐标。

         类似的stepPhysicsWorldSystem从中来获得TriggerEvents。在此存储由引发碰撞事件启用的对象发出的事件。

您所要做的就是让对象与EventTrigger键接触并处理事件。

   protected override void OnUpdate()
    {
        var physicsWorld = buildPhysicsWorldSystem.PhysicsWorld;
        var triggerEvents = stepPhysicsWorldSystem.Simulation.TriggerEvents;
        var items = GetComponentDataFromEntity(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();
        stepPhysicsWorldSystem = World.GetOrCreateSystem();
    }

    protected override void OnUpdate()
    {
        var physicsWorld = buildPhysicsWorldSystem.PhysicsWorld;
        var triggerEvents = stepPhysicsWorldSystem.Simulation.TriggerEvents;
        var items = GetComponentDataFromEntity(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 items)
    {
        if( items.Exists(entity))
        {
            PostUpdateCommands.DestroyEntity(entity);
            UnityEngine.Debug.Log("you get item!");
        }
    }
}

应该注意的是,Unity Physics没有状态,因此似乎不能采取诸如“碰撞开始”,“ 碰撞中”和“ 碰撞结束”之类的事件。

        如果只想在特定对象之间执行碰撞事件,则可以确定在ComponentDataFromEntity中是否具有特定组件,如上面的代码中所示,或者Custom Flag通过设置它BodyA.CustomData

关于Unity 2019中的新物理系统相关_第13张图片

如果您不想简单地触摸,最好调整碰撞滤波器。这里的界面是我希望你再做一点的地方。

关于Unity 2019中的新物理系统相关_第14张图片

我想使用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();
        stepPhysicsWorldSystem = World.GetOrCreateSystem();
        bufferSystem = World.GetOrCreateSystem();
    }

    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(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 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!");
        }
    }
}

 

 

 

 

你可能感兴趣的:(学unity涨知识)