一、创建12000个弹性球体测试
搜索:Unity Physics


创建球体预制体如下脚本设置:

cs
using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
public class PhysicsDemoTest : MonoBehaviour
{
public GameObject prefab;
BlobAssetStore assetStore;
void Start()
{
assetStore = new BlobAssetStore();
GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, assetStore);
Entity entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
Translation translation = new Translation();
for (int i = 0; i < 30; i++)
{
for (int j = 0; j < 20; j++)
{
for (int k = 0; k < 20; k++)
{
Entity entity = entityManager.Instantiate(entityPrefab);
float random = Random.Range(-0.1f, 0.1f);
translation.Value = new Unity.Mathematics.float3(k * 2 + random, i * 2, j * 2 - random);
entityManager.SetComponentData(entity, translation);
}
}
}
}
void OnDestroy()
{
assetStore.Dispose();
}
}
二、ECS 物理 射线检测
代码只创建一个球体,且球体设置为静态的物体。

cs
using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using Unity.Physics.Systems;
using Unity.Physics;
public class PhysicsDemoTest : MonoBehaviour
{
public GameObject prefab;
BlobAssetStore assetStore;
void Start()
{
assetStore = new BlobAssetStore();
GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, assetStore);
Entity entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
Translation translation = new Translation();
Entity entity = entityManager.Instantiate(entityPrefab);
entityManager.SetName(entity, "球体A");
float random = UnityEngine.Random.Range(-0.1f, 0.1f);
translation.Value = new Unity.Mathematics.float3(5, 5, 5);
entityManager.SetComponentData(entity, translation);
Entity entity1 = Raycast(Camera.main.transform.position, Input.mousePosition);
Debug.Log(entityManager.GetName(entity1));
}
void OnDestroy()
{
assetStore.Dispose();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
UnityEngine.Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Entity entity1 = Raycast(ray.origin, ray.GetPoint(100));
Debug.Log(entityManager.GetName(entity1));
}
}
private Entity Raycast(float3 start, float3 end)
{
Debug.DrawLine(start, end, Color.red, 2);
//获取ECS物理系统
BuildPhysicsWorld buildPhysicsWorld = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
//碰撞管理
CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
//相当于Ray
RaycastInput raycastInput = new RaycastInput()
{
Start = start,
End = end,
Filter = CollisionFilter.Default
};
//相当于Hit
Unity.Physics.RaycastHit raycastHit = new Unity.Physics.RaycastHit();
//使用碰撞管理检测input 输出hit
if (collisionWorld.CastRay(raycastInput, out raycastHit))
{
//使用hit的index作为索引从Bodies数组取到碰撞Body 再取实体
Entity entity = buildPhysicsWorld.PhysicsWorld.Bodies[raycastHit.RigidBodyIndex].Entity;
return entity;
}
return Entity.Null;
}
}
使用Job Burst优化代码如下:
注意:不能将BuildPhysicsWorld、CollisionWorld直接传递进Job类,而是将PhysicsWorld传入,使用NativeArray<RigidBody>缓存射线检测到的刚体数组,而不是实体。
cs
using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using Unity.Physics.Systems;
using Unity.Physics;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
public class PhysicsDemoTest : MonoBehaviour
{
public GameObject prefab;
BlobAssetStore assetStore;
void Start()
{
assetStore = new BlobAssetStore();
GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, assetStore);
Entity entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
Translation translation = new Translation();
Entity entity = entityManager.Instantiate(entityPrefab);
entityManager.SetName(entity, "球体A");
float random = UnityEngine.Random.Range(-0.1f, 0.1f);
translation.Value = new Unity.Mathematics.float3(5, 5, 5);
entityManager.SetComponentData(entity, translation);
Entity entity1 = Raycast(Camera.main.transform.position, Input.mousePosition);
Debug.Log(entityManager.GetName(entity1));
}
void OnDestroy()
{
assetStore.Dispose();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
UnityEngine.Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//Entity entity1 = Raycast(ray.origin, ray.GetPoint(100));
//获取ECS物理系统
BuildPhysicsWorld buildPhysicsWorld = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
//碰撞管理
CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
NativeArray<RigidBody> rigidbodies = new NativeArray<RigidBody>(1, Allocator.TempJob);
RaycastJob raycastJob = new RaycastJob()
{
start = ray.origin,
end = ray.GetPoint(100),
physicsWorld = buildPhysicsWorld.PhysicsWorld,
rigidBodies = rigidbodies
};
JobHandle jobHandle = raycastJob.Schedule();
jobHandle.Complete();
if (rigidbodies[0].Entity != null)
{
Debug.Log(entityManager.GetName(rigidbodies[0].Entity));
}
rigidbodies.Dispose();
}
}
[BurstCompile]
public struct RaycastJob : IJob
{
public NativeArray<RigidBody> rigidBodies;
public float3 start;
public float3 end;
public PhysicsWorld physicsWorld;
public void Execute()
{
//相当于Ray
RaycastInput raycastInput = new RaycastInput()
{
Start = start,
End = end,
Filter = CollisionFilter.Default
};
//相当于Hit
Unity.Physics.RaycastHit raycastHit = new Unity.Physics.RaycastHit();
//使用碰撞管理检测input 输出hit
if (physicsWorld.CollisionWorld.CastRay(raycastInput, out raycastHit))
{
//使用hit的index作为索引从Bodies数组取到碰撞Body 再取实体
rigidBodies[0] = physicsWorld.Bodies[raycastHit.RigidBodyIndex];
}
}
}
}
