unity2019 ECS入门实例:创建一个Entity

Unity2019 ECS 入门实例:创建一个Entity

一. 前言

本篇要实现创建一个实体,并将这个Entity在场景中显示出来,用ECS框架来解释就是创建一个Entity,并为这个Entity添加ComponentData从而完成上述功能.

  1. 按我的理解Entity≠GameObject,而 GameObject = (Entity + Component(data) +System)
  2. 想要在场景中显示物体肯定要有Mesh(形状)Material(材质),所以我们要做的是为Entity添加这些Component(数据)
  3. 这个案例没有编写System(行为)

二. 搭建环境

  1. 我的Unity版本:Unity2019.4.7LTS
  2. 使用Window->PackageManage 搜索Entities,点击Install,记得勾选 show preview packages
  3. 同理安装Jobs,Mathematics,Hybrid Render
  4. 安装完成后即可开始编码了,以上步骤有问题可以自行搜索对应的问题或者留言

三. 编码实现创建一个Entity,并在场景中显示

在Unity中,提供了很多方法去创建或者将GameObject转换成Entity,这里我们主要采用创建的方式,在新建的项目中,创建一个脚本CreateEntity.cs

CreateEntity.cs

using Unity.Entities;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;

public class CreateEntity : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        manager = World.DefaultGameObjectInjectionWorld.EntityManager;//获取默认世界的实体管理器
        CreateEntityObj();
    }

    // Update is called once per frame
    void Update()
    {
        
    }


    private EntityManager manager;
    private void CreateEntityObj()
    {
        //在EntityManager中提供了public Entity CreateEntity(EntityArchetype archetype);方法
        //在此之前,我们需要一个
        //同样在EntityManager中,有一个 CreateArchetype(params ComponentType[] types);方法
        var archeType = manager.CreateArchetype
        (
            //以下等于规定了Entity中一系列数据类型
            ComponentType.ReadWrite<LocalToWorld>(),
            ComponentType.ReadWrite<Translation>(),
            ComponentType.ReadOnly<RenderMesh>()
        );

        var entity = manager.CreateEntity(archeType);//到此我们就创建了一个entity
        manager.SetName(entity, "cube");//设置一个名字方便观察

        //需要为Entity设置位置,形状,材质等信息,这里的信息可以使用公有变量在检视面板中设置
        //此处直接使用一个标准的数据
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

        //为实体设置数据
        manager.SetComponentData<LocalToWorld>(entity, new LocalToWorld() { Value = Unity.Mathematics.float4x4.zero });
        manager.SetComponentData<Translation>(entity, new Translation() { Value = new Unity.Mathematics.float3(0, 0, 0) });
        manager.SetSharedComponentData<RenderMesh>(entity, new RenderMesh()
        {
            material = cube.GetComponent<MeshRenderer>().material,
            mesh = cube.GetComponent<MeshFilter>().sharedMesh,
            subMesh = 0,
            castShadows = UnityEngine.Rendering.ShadowCastingMode.On,
            receiveShadows = true,
            needMotionVectorPass = true
        });

        Destroy(cube);//临时使用的cube进行销毁
    }
}

但是!挂载运行后在在场景中并没有找到我我们想要的那个Cube,但是在Entity Debugger中可以看到那个Entity确实已经存在了,那就说明场景中应该是有的,只能说我们没找到。

四. 问题解决

Entity Debugger中有,场景中看不到,那就说明为他设置位置的数据有问题。

  1. 在场景中新建一个Cube,并添加ConvertToEntity脚本
  2. 运行然后打开Entity Debugger,查看转换成的Entity,发现多了几个数据,数据类型都是render bounds相关的
  3. Entity添加RenderBounds数据

第一次运行,Entity的信息
添加Renderbounds后

修改后的CreateEntity.cs

using Unity.Entities;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;

public class CreateEntity : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        manager = World.DefaultGameObjectInjectionWorld.EntityManager;//获取默认世界的实体管理器
        CreateEntityObj();
    }

    // Update is called once per frame
    void Update()
    {
        
    }


    private EntityManager manager;
    private void CreateEntityObj()
    {
        //在EntityManager中提供了public Entity CreateEntity(EntityArchetype archetype);方法
        //在此之前,我们需要一个
        //同样在EntityManager中,有一个 CreateArchetype(params ComponentType[] types);方法
        var archeType = manager.CreateArchetype
        (
            //以下等于规定了Entity中一系列数据类型
            ComponentType.ReadWrite<LocalToWorld>(),
            ComponentType.ReadWrite<Translation>(),
            ComponentType.ReadOnly<RenderMesh>(),
            ComponentType.ReadWrite<RenderBounds>()
        );

        var entity = manager.CreateEntity(archeType);//到此我们就创建了一个entity
        manager.SetName(entity, "cube");//设置一个名字方便观察

        //需要为Entity设置位置,形状,材质等信息,这里的信息可以使用公有变量在检视面板中设置
        //此处直接使用一个标准的数据
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

        //为实体设置数据
        RenderBounds rb = new RenderBounds()
        {
            Value = new Unity.Mathematics.AABB()
            {
                Center = new Unity.Mathematics.float3(0, 0, 0),
                Extents = new Unity.Mathematics.float3(0.5f,0.5f,0.5f)
            }
        };
        manager.SetComponentData<RenderBounds>(entity,rb)//只需添加archerType即可,不需要手动设置数据
        manager.SetComponentData<LocalToWorld>(entity, new LocalToWorld() { Value = Unity.Mathematics.float4x4.zero });
        manager.SetComponentData<Translation>(entity, new Translation() { Value = new Unity.Mathematics.float3(0, 0, 0) });
        manager.SetSharedComponentData<RenderMesh>(entity, new RenderMesh()
        {
            material = cube.GetComponent<MeshRenderer>().material,
            mesh = cube.GetComponent<MeshFilter>().sharedMesh,
            subMesh = 0,
            castShadows = UnityEngine.Rendering.ShadowCastingMode.On,
            receiveShadows = true,
            needMotionVectorPass = true
        });

        Destroy(cube);//临时使用的cube进行销毁
    }
}

欢迎访问我的个人博客 Snail’s Blog
转载请注明出处,侵权必究!!!https://blog.csdn.net/weixin_36382492/article/details/109266676

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页