【Unity3D】ECS入门学习(十三)Unity Physics

[复制链接]
发表于 2025-11-17 15:29:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、创建12000个弹性球体测试

搜刮:Unity Physics


创建球体预制体如下脚本设置:
 
  1. using UnityEngine;
  2. using Unity.Entities;
  3. using Unity.Transforms;
  4. public class PhysicsDemoTest : MonoBehaviour
  5. {
  6.     public GameObject prefab;
  7.     BlobAssetStore assetStore;
  8.     void Start()
  9.     {
  10.         assetStore = new BlobAssetStore();
  11.         GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, assetStore);
  12.         Entity entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
  13.         EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
  14.         Translation translation = new Translation();
  15.         for (int i = 0; i < 30; i++)
  16.         {
  17.             for (int j = 0; j < 20; j++)
  18.             {
  19.                 for (int k = 0; k < 20; k++)
  20.                 {
  21.                     Entity entity = entityManager.Instantiate(entityPrefab);
  22.                     float random = Random.Range(-0.1f, 0.1f);
  23.                     translation.Value = new Unity.Mathematics.float3(k * 2 + random, i * 2, j * 2 - random);
  24.                     entityManager.SetComponentData(entity, translation);
  25.                 }
  26.             }
  27.         }
  28.     }
  29.     void OnDestroy()
  30.     {
  31.         assetStore.Dispose();
  32.     }
  33. }
复制代码
二、ECS 物理 射线检测

代码只创建一个球体,且球体设置为静态的物体。
  1. using UnityEngine;
  2. using Unity.Entities;
  3. using Unity.Transforms;
  4. using Unity.Mathematics;
  5. using Unity.Physics.Systems;
  6. using Unity.Physics;
  7. public class PhysicsDemoTest : MonoBehaviour
  8. {
  9.     public GameObject prefab;
  10.     BlobAssetStore assetStore;
  11.     void Start()
  12.     {
  13.         assetStore = new BlobAssetStore();
  14.         GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, assetStore);
  15.         Entity entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
  16.         EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
  17.         Translation translation = new Translation();
  18.         Entity entity = entityManager.Instantiate(entityPrefab);
  19.         entityManager.SetName(entity, "球体A");
  20.         float random = UnityEngine.Random.Range(-0.1f, 0.1f);
  21.         translation.Value = new Unity.Mathematics.float3(5, 5, 5);
  22.         entityManager.SetComponentData(entity, translation);
  23.         Entity entity1 = Raycast(Camera.main.transform.position, Input.mousePosition);
  24.         Debug.Log(entityManager.GetName(entity1));
  25.     }
  26.     void OnDestroy()
  27.     {
  28.         assetStore.Dispose();
  29.     }
  30.     void Update()
  31.     {
  32.         if (Input.GetMouseButtonDown(0))
  33.         {
  34.             EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
  35.             UnityEngine.Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  36.             Entity entity1 = Raycast(ray.origin, ray.GetPoint(100));
  37.             Debug.Log(entityManager.GetName(entity1));
  38.         }
  39.     }
  40.     private Entity Raycast(float3 start, float3 end)
  41.     {
  42.         Debug.DrawLine(start, end, Color.red, 2);
  43.         //获取ECS物理系统
  44.         BuildPhysicsWorld buildPhysicsWorld = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
  45.         //碰撞管理
  46.         CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
  47.         //相当于Ray
  48.         RaycastInput raycastInput = new RaycastInput()
  49.         {
  50.             Start = start,
  51.             End = end,
  52.             Filter = CollisionFilter.Default
  53.         };
  54.         //相当于Hit
  55.         Unity.Physics.RaycastHit raycastHit = new Unity.Physics.RaycastHit();
  56.         //使用碰撞管理检测input 输出hit
  57.         if (collisionWorld.CastRay(raycastInput, out raycastHit))
  58.         {
  59.             //使用hit的index作为索引从Bodies数组取到碰撞Body 再取实体
  60.             Entity entity = buildPhysicsWorld.PhysicsWorld.Bodies[raycastHit.RigidBodyIndex].Entity;
  61.             return entity;
  62.         }
  63.         return Entity.Null;
  64.     }
  65. }
复制代码
利用Job Burst优化代码如下:
注意:不能将BuildPhysicsWorld、CollisionWorld直接转达进Job类,而是将PhysicsWorld传入,利用NativeArray<RigidBody>缓存射线检测到的刚体数组,而不是实体。
  1. using UnityEngine;
  2. using Unity.Entities;
  3. using Unity.Transforms;
  4. using Unity.Mathematics;
  5. using Unity.Physics.Systems;
  6. using Unity.Physics;
  7. using Unity.Jobs;
  8. using Unity.Collections;
  9. using Unity.Burst;
  10. public class PhysicsDemoTest : MonoBehaviour
  11. {
  12.     public GameObject prefab;
  13.     BlobAssetStore assetStore;
  14.     void Start()
  15.     {
  16.         assetStore = new BlobAssetStore();
  17.         GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, assetStore);
  18.         Entity entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
  19.         EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
  20.         Translation translation = new Translation();
  21.         Entity entity = entityManager.Instantiate(entityPrefab);
  22.         entityManager.SetName(entity, "球体A");
  23.         float random = UnityEngine.Random.Range(-0.1f, 0.1f);
  24.         translation.Value = new Unity.Mathematics.float3(5, 5, 5);
  25.         entityManager.SetComponentData(entity, translation);
  26.         Entity entity1 = Raycast(Camera.main.transform.position, Input.mousePosition);
  27.         Debug.Log(entityManager.GetName(entity1));
  28.     }
  29.     void OnDestroy()
  30.     {
  31.         assetStore.Dispose();
  32.     }
  33.     void Update()
  34.     {
  35.         if (Input.GetMouseButtonDown(0))
  36.         {
  37.             EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
  38.             UnityEngine.Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  39.             //Entity entity1 = Raycast(ray.origin, ray.GetPoint(100));
  40.             //获取ECS物理系统
  41.             BuildPhysicsWorld buildPhysicsWorld = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
  42.             //碰撞管理
  43.             CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
  44.             NativeArray<RigidBody> rigidbodies = new NativeArray<RigidBody>(1, Allocator.TempJob);
  45.             RaycastJob raycastJob = new RaycastJob()
  46.             {
  47.                 start = ray.origin,
  48.                 end = ray.GetPoint(100),
  49.                 physicsWorld = buildPhysicsWorld.PhysicsWorld,
  50.                 rigidBodies = rigidbodies
  51.             };
  52.             JobHandle jobHandle = raycastJob.Schedule();
  53.             jobHandle.Complete();
  54.             if (rigidbodies[0].Entity != null)
  55.             {
  56.                 Debug.Log(entityManager.GetName(rigidbodies[0].Entity));
  57.             }
  58.             rigidbodies.Dispose();
  59.         }
  60.     }
  61.     [BurstCompile]
  62.     public struct RaycastJob : IJob
  63.     {
  64.         public NativeArray<RigidBody> rigidBodies;
  65.         public float3 start;
  66.         public float3 end;
  67.         public PhysicsWorld physicsWorld;
  68.         public void Execute()
  69.         {
  70.             //相当于Ray
  71.             RaycastInput raycastInput = new RaycastInput()
  72.             {
  73.                 Start = start,
  74.                 End = end,
  75.                 Filter = CollisionFilter.Default
  76.             };
  77.             //相当于Hit
  78.             Unity.Physics.RaycastHit raycastHit = new Unity.Physics.RaycastHit();
  79.             //使用碰撞管理检测input 输出hit
  80.             if (physicsWorld.CollisionWorld.CastRay(raycastInput, out raycastHit))
  81.             {
  82.                 //使用hit的index作为索引从Bodies数组取到碰撞Body 再取实体
  83.                 rigidBodies[0] = physicsWorld.Bodies[raycastHit.RigidBodyIndex];
  84.             }
  85.         }
  86.     }
  87. }
复制代码
 
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表