【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];
            }
        }
    }
}
相关推荐
Gain_chance9 小时前
36-学习笔记尚硅谷数仓搭建-DWS层数据装载脚本
大数据·数据仓库·笔记·学习
XH华9 小时前
备战蓝桥杯,第九章:结构体和类
学习·蓝桥杯
Gain_chance9 小时前
35-学习笔记尚硅谷数仓搭建-DWS层最近n日汇总表及历史至今汇总表建表语句
数据库·数据仓库·hive·笔记·学习
Ziky学习记录11 小时前
从零到实战:React Router 学习与总结
前端·学习·react.js
sensen_kiss11 小时前
INT303 Coursework1 爬取影视网站数据(如何爬虫网站数据)
爬虫·python·学习
red_redemption12 小时前
自由学习记录(116)
学习
r i c k13 小时前
数据库系统学习笔记
数据库·笔记·学习
野犬寒鸦13 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习
浅念-14 小时前
C语言编译与链接全流程:从源码到可执行程序的幕后之旅
c语言·开发语言·数据结构·经验分享·笔记·学习·算法
ZH154558913114 小时前
Flutter for OpenHarmony Python学习助手实战:API接口开发的实现
python·学习·flutter