返回

ECS问题记录

开发过程中所遇到问题

  1. 如何存放Unity引用对象?(材质、网格)

    目前知道的,只能在ISharedComponentData中存放Unity引用对象,且还需要继承IEquatable接口,并实现EqualsGetHashCode方法。

  2. 如何修改单个物体的共享组件(ISharedComponentData)值。

    由共享组件设计可以得知,在给Entity设定相同参数的共享组件时,这些Entity实际上都指向同一地址,也就是说,本质上只有一个共享组件,所以无论你修改任何Entity的ISharedComponentData参数,其他Entity也会发生改变。

    修改ISharedComponentData参数的唯一办法,就是再创建一个ISharedComponentData,然后将该组件设置给Entity。

  3. 如何使用EntityQuery筛选组件相同,但组件参数不同的Entity

    暂时不知道是什么原因,我们定义了两个EntityQuery字段,且New了一个新的EntityQueryDesc,但当我们筛选相同类型组件(其中某个组件值进行了特定筛选),他们筛选出来的结果却是相同的,就像两个EntityQuery指向的是同一地址。

    解决办法也非常奇特,就是在筛选条件下额外添加一个筛选组件条件,只要两个EntityQuery筛选条件的组件个数类型不相等,那么他们筛选出的结果就肯定不相同。

  4. 如何在Job中增添删除Entity的组件。

    这里需要用到EndSimulationEntityCommandBufferSystem

    在OnCreate方法中创建EndSimulationEntityCommandBufferSystem:

        private EndSimulationEntityCommandBufferSystem m_EntityCommandBufferSystem;
    
        protected override void OnCreate()
        {
            m_EntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
        }
    

    然后在OnUpdate中使用,删除Entity

     var commandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer();
     ......
     commandBuffer.DestroyEntity(entity);
    
  5. 如何用一组Entity去比较另一组Entity?

    多种方法,第一种,在Entities.ForEach()嵌套使用Entities.ForEach()(看了网上教程才知道还可以这样用)

    第二种,使用两个EntityQuery对Entity进行筛选,然后使用EntityQuery.ToEntityArray(Allocator.TempJob)方法转换成NativeArray,后面直接对数组进行比较操作就可以了

  6. 如何通过Entity获取其身上的组件。

    方法如下:

       UnitCombatComponent EnemyCombatComponent = EntityManager.GetComponentData<UnitCombatComponent>(entity);
    
  7. 如何修改物体的颜色

    一开始我在做Demo的时候也很想修改,直到我发现ECS用于渲染的组件RenderMesh是共享组件后我傻了。

    然后我专念自己创建组件进行手动渲染:

    using Unity.Entities;
    using UnityEngine;
    using System;
    
     struct UnitRenderMeshComponent : ISharedComponentData, IEquatable<UnitRenderMeshComponent>
    {
        public Mesh mesh;
    
        public int layer;
    
        public bool Equals(UnitRenderMeshComponent other)
        {
            return other.mesh == this.mesh;
        }
        public override int GetHashCode()
        {
            return mesh.GetHashCode();
        }
    }
     struct UnitRenderMaterialComponent : ISharedComponentData, IEquatable<UnitRenderMaterialComponent>
    {  
        public Material material;
    
        public bool Equals(UnitRenderMaterialComponent other)
        {
            return other.material == this.material;
        }
        public override int GetHashCode()
        {
            return material.GetHashCode();
        }
    }
    
    
    
    
    [UpdateInGroup(typeof(UpdatePresentationSystemGroup))]
    public class UnitRenderMeshSystem : SystemBase
    {
        protected override void OnUpdate()
        {
            Entities.ForEach((UnitRenderMeshComponent renderMesh, UnitRenderMaterialComponent renderMater, LocalToWorld localToWorld) =>
            {
                Graphics.DrawMesh(mesh: renderMesh.mesh, matrix: localToWorld.Value, material: renderMater.material, layer: renderMesh.layer);
            }).WithoutBurst().Run();
        }
    }
    

    但这样还是很麻烦,每次像修改物体颜色,需要重新创建UnitRenderMaterialComponent组件,然后赋值新的材质。

  8. Entity顺序问题。

    在Entity中顺序并不是固定的。我们知道Entity所携带组件发生改变时会改变其所在的块,由于块发生了改变,所以entity在总体的数组中的Index也会随之发生改变。

一些知识点参考网址

EntityQuery:https://blog.csdn.net/weixin_40124181/article/details/103855181

System执行顺序:http://www.benmutou.com/archives/2823

各种Component:http://www.benmutou.com/archives/2840

Schedule相关:https://www.cnblogs.com/tiancaiwrk/p/12410825.html

Licensed under CC BY-NC-SA 4.0
0