Unity DOTS中的物理系统即Unity.Physics,这里使用一个简单的demo(小球相撞效果),来说明一下 碰撞 Collision。
1、创建两个sphere(注意,要去掉ShpereCollider),添加Physics Shape,ShapeType 选择 Sphere,PhysicsShape 选择Collide Raise Collision Events。新建CollisionFilter类型Sphere和Plane,然后设置 BelongsTo = Sphere,设置CollidesWith = Sphere, Plane;添加 Physics Body。
2、创建三个plane(注意,要去掉MeshCollider),添加Physics Shape,ShapeType 选择 Plane,PhysicsShape 选择Collide。然后设置 CollisionFilter, BelongsTo = Plane,设置CollidesWith = Sphere;添加 Physics Body,MotionType设为Kinematic。
3、小球碰撞,触发逻辑
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.Physics;
using Unity.Collections;
using Unity.Physics.Systems;
public class PhysicalSystem : SystemBase
{
private BuildPhysicsWorld buildPhysicsWorld;//物理系统的准备工作,将TriggerCollisionEvents传递给Job
private StepPhysicsWorld stepPhysicsWorld;//物理系统的准备工作,将TriggerCollisionEvents传递给Job
protected override void OnCreate()
{
buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
}
protected override void OnUpdate()
{
ColliderJob colliderJob = new ColliderJob()
{
velocitys = GetComponentDataFromEntity<PhysicsVelocity>()
};
Dependency = colliderJob.Schedule(stepPhysicsWorld.Simulation, ref buildPhysicsWorld.PhysicsWorld, Dependency);
}
}
public struct ColliderJob : ICollisionEventsJob
{
public ComponentDataFromEntity<PhysicsVelocity> velocitys;
public void Execute(CollisionEvent collisionEvent)
{
if (velocitys.HasComponent(collisionEvent.EntityA) && IsSphere(collisionEvent.EntityA, "Sphere"))
{
if (velocitys.HasComponent(collisionEvent.EntityB) && IsSphere(collisionEvent.EntityB, "Sphere"))
{
var velocityA = velocitys[collisionEvent.EntityA];
var dirA = -math.sign(velocityA.Linear.x);
//Debug.Log("dirA = " + dirA);
velocityA.Linear.x = dirA * 20;
velocitys[collisionEvent.EntityA] = velocityA;
var velocityB = velocitys[collisionEvent.EntityB];
var dirB = -math.sign(velocityB.Linear.x);
//Debug.Log("dirB = " + dirB);
velocityB.Linear.x = dirB * 20;
velocitys[collisionEvent.EntityB] = velocityB;
}
}
}
public bool IsSphere(Entity entity, string name)
{
return World.DefaultGameObjectInjectionWorld.EntityManager.GetName(entity) == name;
}
}