Dots最简实践(二),添加碰撞

导入Unity Physics包,并且导入 Samples 案例,否则没有碰撞信息。
1.首先是墙壁,有Collider组件就行

2.然后是子弹设置,因为子弹是运动的,需要添加PhysicsShape,并且设置Collision Response 设置为 Collide Raise Collision Events,同时给子弹添加Rigidbody

3.最后是代码
using Unity.Burst; using Unity.Collections; using Unity.Entities; using Unity.Physics; using Unity.Physics.Systems; using UnityEngine; [BurstCompile] [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))] public partial struct BulletCollisionSystem : ISystem { [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate<EndFixedStepSimulationEntityCommandBufferSystem.Singleton>(); state.RequireForUpdate<SimulationSingleton>(); // 物理仿真单例 } [BurstCompile] public void OnUpdate(ref SystemState state) { var ecb = SystemAPI .GetSingleton<EndFixedStepSimulationEntityCommandBufferSystem.Singleton>() .CreateCommandBuffer(state.WorldUnmanaged) .AsParallelWriter(); var job = new CollisionJob { BulletLookup = SystemAPI.GetComponentLookup<BulletTag>(true), WallLookup = SystemAPI.GetComponentLookup<WallTag>(true), Ecb = ecb }; var sim = SystemAPI.GetSingleton<SimulationSingleton>(); state.Dependency = job.Schedule(sim, state.Dependency); } [BurstCompile] private struct CollisionJob : ICollisionEventsJob { [ReadOnly] public ComponentLookup<BulletTag> BulletLookup; [ReadOnly] public ComponentLookup<WallTag> WallLookup; public EntityCommandBuffer.ParallelWriter Ecb; public void Execute(CollisionEvent evt) { var a = evt.EntityA; var b = evt.EntityB; if (BulletLookup.HasComponent(a) && WallLookup.HasComponent(b)) { Ecb.DestroyEntity(0, a); // sortKey 用 0 即可 Debug.LogError("销毁物体A"); } else if (BulletLookup.HasComponent(b) && WallLookup.HasComponent(a)) { Ecb.DestroyEntity(0, b); Debug.LogError("销毁物体B"); } } } } public struct BulletTag : IComponentData {} public struct WallTag : IComponentData {}
using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Entities; public class WallAuthoring : MonoBehaviour { class Baker : Baker<WallAuthoring> { public override void Bake(WallAuthoring authoring) { // 为当前GameObject创建或获取对应的Entity。 // TransformUsageFlags.Dynamic 的含义:动态的,表示这个对象的Transform会频繁变化,比如:移动的玩家、子弹、敌人等 var entity = GetEntity(TransformUsageFlags.Renderable); // 给枪械添加输入组件 AddComponent(entity, new WallTag()); } } }
记得给子弹添加对应的Tag
对ShotSystem做了一些修改
using Unity.Collections; using Unity.Entities; using Unity.Mathematics; using Unity.Transforms; using Unity.Burst; using Unity.Jobs; using UnityEngine; using Unity.Rendering; // 输入组件 public struct PlayerInputComponent : IComponentData { public bool firePressed; // 是否按下开火键 } // 枪械组件 public struct GunComponent : IComponentData { public int bulletsPerShot; // 每次射击的子弹数量 public float bulletSpeed; // 子弹速度 public float bulletLifetime; // 子弹生存时间 public float damage; // 每颗子弹伤害 public Entity bulletPrefab; // 子弹预制体实体 } // 子弹组件,包含子弹的基本属性 public struct BulletComponent : IComponentData { public float3 velocity; // 速度向量 public float lifetime; // 剩余生存时间 public float maxLifetime; // 最大生存时间 public float damage; // 伤害值 public float speed; // 速度大小 } [UpdateInGroup(typeof(SimulationSystemGroup))] public partial struct ShotSystem : ISystem { private Unity.Mathematics.Random myRandom; [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate<BeginSimulationEntityCommandBufferSystem.Singleton>(); myRandom = new Unity.Mathematics.Random(1234); } [BurstCompile] public void OnUpdate(ref SystemState state) { // 获取枪械 var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager; var playerGunEntity = entityManager.CreateEntityQuery(typeof(PlayerInputComponent)).GetSingletonEntity(); //获取输入组件有没有开火 var input = entityManager.GetComponentData<PlayerInputComponent>(playerGunEntity); if (!input.firePressed) { return; } Debug.Log("按下了开火按钮"); // 在第一次运行时获取并缓存 var ecb = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>(); var ecbWrite = ecb.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter(); // 处理射击 var fireJob = new FireBulletsJob { ECB = ecbWrite, random = myRandom, }; state.Dependency = fireJob.ScheduleParallel(state.Dependency);//固定写法,排队执行 } [BurstCompile] public partial struct FireBulletsJob : IJobEntity { public EntityCommandBuffer.ParallelWriter ECB; public Unity.Mathematics.Random random; void Execute([EntityIndexInQuery] int entityInQueryIndex, in GunComponent shotgun, in LocalTransform transform) { // 计算发射方向(假设向前发射) float3 forward = math.forward(transform.Rotation); // 发射子弹 for (int i = 0; i < shotgun.bulletsPerShot; i++) { // 计算子弹方向 float3 bulletDirection = forward; // 创建子弹实体 var bulletEntity = ECB.Instantiate(entityInQueryIndex, shotgun.bulletPrefab); // 设置子弹位置(在枪口位置稍微前面一点) int rangeX = random.NextInt(0, 100); int rangeY = random.NextInt(0, 100); int rangeZ = random.NextInt(0, 10); float3 spawnPosition = transform.Position + forward * 2f + new float3(rangeX, rangeY, rangeZ); ECB.SetComponent(entityInQueryIndex, bulletEntity, LocalTransform.FromPositionRotation( spawnPosition, quaternion.LookRotationSafe(bulletDirection, math.up()) )); // 添加子弹组件 ECB.AddComponent(entityInQueryIndex, bulletEntity, new BulletComponent { velocity = bulletDirection * shotgun.bulletSpeed, lifetime = shotgun.bulletLifetime, maxLifetime = shotgun.bulletLifetime, damage = shotgun.damage, speed = shotgun.bulletSpeed }); ECB.AddComponent(entityInQueryIndex, bulletEntity, new BulletTag()); } } } } public static class MyHelper { public static int xx = 99; }

浙公网安备 33010602011771号