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

一、创建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];
            }
        }
    }
}
相关推荐
Canmag 兴隆磁性2 分钟前
C 系列充磁机
c语言·开发语言·学习·永磁材料·充磁·退磁
新手unity自用笔记1 小时前
unity基于Socket的网络学习
网络·网络协议·学习·unity·c#·游戏引擎
zyf1044161 小时前
暑期实践日志 Day32:完成第六章字幕添加,推进工作
学习·计算机网络·剪辑·暑期实践·课题任务
小雪崩2 小时前
嵌入式学习 day27:标准IO
linux·c语言·学习
hsjiasb2 小时前
FreeRTOS学习(三十五)——系统架构综合项目
学习·学习笔记·freertos
YM52e2 小时前
语言地区选择器-鸿蒙ArkTS国际化页面设计
学习·华为·harmonyos
不是光头 强2 小时前
Java 后端 AI 技术选型与学习路线
java·人工智能·学习
cloudification2 小时前
virtual
学习
MartinYeung53 小时前
[论文学习]δ-STEAL:基于本地差分隐私的大语言模型窃取攻击
网络·学习·语言模型
paopaokaka_luck3 小时前
基于springboot3+vue3的文山民族文化资源展示与推广平台(协同过滤算法、Echarts 图形化分析)
java·前端·spring boot·学习·echarts