【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];
            }
        }
    }
}
相关推荐
宝绿特塑业再生科技1 小时前
改性HDPE再生颗粒在户外家具挤出发泡板材中的色差控制与高品质价值重构
经验分享·科技·学习·生活·1024程序员节·户外家具
andrsted3 小时前
练题簿在线免费刷题:让整理过的资料,变成能反复练习的题库
学习·微信小程序·小程序·学习方法·刷题·1024程序员节
Alsn864 小时前
Windows 安装 Ollama 及本地模型部署
学习·1024程序员节
欣欣之王来了5 小时前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
小贺儿开发6 小时前
《长征 · 征途》Unity 三维互动沙盘
科技·3d·unity·1024程序员节·地形·互动·沙盘
解决小子7 小时前
【虚幻引擎】【C++】【GAS框架】构建角色基类、属性集、数值钳制
c++·笔记·游戏引擎·虚幻·gas·能力系统
知识分享小能手7 小时前
C学习教程,从入门到精通,C语言学生信息管理系统 — 知识点详解(18)
c语言·学习·1024程序员节
上班摸鱼下班游戏8 小时前
Unity 仿生智能算法 从蚁群算法 开始
算法·unity·游戏引擎
破芽8 小时前
learn-claude-code-s05-s11-学习笔记
笔记·学习
pipixia200338 小时前
C++ 面试高频:namespace 的 6 个知识点,从 using 到匿名命名空间
c语言·学习·算法·嵌入式·命名空间·c++面试·匿名命名空间