【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];
            }
        }
    }
}
相关推荐
JWASX几秒前
Java 转 go 学习 - 函数(1)
学习·golang
sunshine22 girl1 分钟前
Java学习五 面向对象高级5 内部类3-静态内部类和局部内部类(了解)
java·学习
小师兄吃牛肉19 分钟前
什么是R语言?如何快速学习R语言
开发语言·学习·r语言
传奇开心果编程35 分钟前
【ArkUI进阶练中学】第5课:编译优化与包体积进
学习·ui·华为·harmonyos
bing.shao1 小时前
让机器从数据中生成本领:诺因Knowin通用具身智能生成式学习架构GLOW深度解析
学习·架构
阳光九叶草LXGZXJ1 小时前
达梦数据库-学习-69-DM9主备集群部署
linux·运维·服务器·数据库·sql·学习
Molesidy1 小时前
【Embedded Development】【高级MCU篇】基于野火STM32H750XBH6_Pro开发板的高级MCU开发学习之1点亮led
stm32·单片机·学习
星恒随风2 小时前
Linux开发工具详解(一):软件包管理、Vim、GCC/G++、Makefile与进度条实战
linux·运维·笔记·学习·vim
传奇开心果编程2 小时前
【ArkUI进阶练中学】第10课:架构设计与工程化最佳实践
学习·ui·华为·harmonyos