【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];
            }
        }
    }
}
相关推荐
抠脚学代码41 分钟前
Ubuntu18.6 学习QT问题记录以及虚拟机安装Ubuntu后的设置
qt·学习·ubuntu
萌新小码农‍8 小时前
Spring框架学习day7--SpringWeb学习(概念与搭建配置)
学习·spring·状态模式
蓝婷儿8 小时前
6个月Python学习计划 Day 15 - 函数式编程、高阶函数、生成器/迭代器
开发语言·python·学习
行云流水剑8 小时前
【学习记录】深入解析 AI 交互中的五大核心概念:Prompt、Agent、MCP、Function Calling 与 Tools
人工智能·学习·交互
海尔辛8 小时前
Unity UI 性能优化--Sprite 篇
ui·unity·性能优化
一弓虽8 小时前
zookeeper 学习
分布式·学习·zookeeper
苗老大8 小时前
MMRL: Multi-Modal Representation Learning for Vision-Language Models(多模态表示学习)
人工智能·学习·语言模型
xhyu619 小时前
【学习笔记】On the Biology of a Large Language Model
笔记·学习·语言模型
小白杨树树9 小时前
【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理
笔记·学习