Unity ECS之Entitas学习笔记(一)

1.Entity的大致说明


Entity就是实体,它不包括数据和执行逻辑,只是一个id标识,但它可以添加组件以及移除组件来行成一个Group组。

1.1.Entity的添加


其中Entity实体的生成只能通过上下文来生成
contex.CreateEntity();
当生成实体后,可以根据实体来进行组件的添加和移除,但这里的移除并不是真正的移除,而是会添加到上下文的对象池中

2.Entity对组件的操作说明

如何添加移除组件,当组件写出后,可以进行代码生成,代码生成会自动为实体生成一个partial类,这个类会根据组件的标签来确定名字。

2.1示例


比如我们创建了一个InterationExampleView组件继承了IComponent,它的标签是Game,那么生成代码就会生成一个内部类GameEntity,这个内部类只负责处理PositionComponent组件的操作,比如加这个组件或者替换这个组件这里只关注Add和Replace,我们发现它们的前三行代码都相同,大概意思就是先从一个类中拿到index,以及创建这个组件,并且给新的组件赋值,然后才是具体的添加或者代替的操作

    public void AddInterationExampleView(UnityEngine.Transform newViewTrans) {
        var index = GameComponentsLookup.InterationExampleView;
        var component = (InterationExample.ViewComponent)CreateComponent(index, typeof(InterationExample.ViewComponent));
        component.viewTrans = newViewTrans;
        AddComponent(index, component);
    }

    public void ReplaceInterationExampleView(UnityEngine.Transform newViewTrans) {
        var index = GameComponentsLookup.InterationExampleView;
        var component = (InterationExample.ViewComponent)CreateComponent(index, typeof(InterationExample.ViewComponent));
        component.viewTrans = newViewTrans;
        ReplaceComponent(index, component);
    }


两个重要属性,分别是得到实体的具体组件以及是否有这个组件,这两个属性一般用于反应式系统中的Filter和GetTrigger中来得到一个收集器以及筛选需要进入Execute方法的实体集合

    public InterationExample.ViewComponent interationExampleView { get { return (InterationExample.ViewComponent)GetComponent(GameComponentsLookup.InterationExampleView); } }
    public bool hasInterationExampleView { get { return HasComponent(GameComponentsLookup.InterationExampleView); } }

3.Component说明


Component是ECS中的数据重要的载体,也是System与Entity操作的对象。它只包含数据,当然这个数据可以是一个引用,也可以只是单纯的数据,甚至可以没有数据(这里即使没有数据,继承的接口也会给一个数据,一般用于标志变量)。

3.1 Component的基本形式


①首先可以选择给不给若干个标签,这个标签是自己定义的,不同的标签会对生成的代码的去向造成影响,其中有一个Unique定义全局唯一的组件数据,其中还有一种标签为[Event(EventTarget.Any/Self)]当有这个标签时,我们自动生成代码会生成一个接口,当这个组件数据改变时会调用实现接口的方法
②其次对数据也可以打上标签,比如[EntityIndex]标签,如果打上这个标签,则生成代码是会自动生成两个扩展方法,在其他任何类中,哪怕是继承了Mono的或者是Input中,都可以根据这两个方法来查找实体。其中一个方法可以为根据一个二维的向量来获取有这个实体的组件,可以是某个点或者其他的。还有一个是根据名字找。这两个方法返回的都是哈希表。

    [Game,Event(EventTarget.Any)]
    public class NameComponent : IComponent
    {
        [EntityIndex]
        public string name;
    }


该示例就是一个组件类的写法

3.2 Component组件的替换与添加

组件替换与添加离不开实体,这里可以在2.1看到,实体会操控这两个函数以实现添加或者移除组件,当数据更新时要调用.示例可以看4.1.2

4.System说明


System是实现逻辑的地方,在Entitas中可通过响应式系统来实现逻辑操作。

4.1 ReactiveSystem说明


它是响应式系统,通常我们自己写的某些System需要继承它,只有当满足某些条件时才会执行,它有三个抽象方法必须实现,分别是

protected abstract ICollector<TEntity> GetTrigger(IContext<TEntity> context);
protected abstract bool Filter(TEntity entity);
protected abstract void Execute(List<TEntity> entities);


其中GetTrigger()返回一个收集器,这个收集器会返回所有上下文匹配的实体的集合,它会在系统初始化时调用
Filter()是筛选器,它进一步筛选符合条件的实体去执行Execute,这个一般都会用到自动生成代码的两个属性进行筛选
Execute()就是对所有符合条件的实体进行组件数据的更新的方法,也是逻辑核心执行的地方

4.2 示例

    public class AddViewSystem : ReactiveSystem<GameEntity>
    {
    //父物体的Transform
        private Transform parent;
    //上下文
        private Contexts contexts;
        public AddViewSystem(Contexts contexts) :base(contexts.game)
        {
            parent = new GameObject("ViewParent").transform;
            this.contexts = contexts;
        }
        protected override void Execute(List<GameEntity> entities)
        {
            foreach(GameEntity entity in entities)
            {
        //实例化一个物体
                GameObject go = new GameObject("View");
        //设置父物体
                go.transform.SetParent(parent);
        //将物体 与实体与上下文联系起来
                go.Link(entity, contexts.game);
        //添加View组件,因为筛选器是筛选的没有这个组件的实体
                entity.AddInterationExampleView(go.transform);
        //设置实体MoveComplete的数据
                entity.isInterationExampleMoveComplete = true;
            }
        }

        protected override bool Filter(GameEntity entity)
        {
        //一般has。。。表示有无这个组件,is。。。表示是否是这个状态,它只是一个表示变量,当Component没有数据时自动生成
                return entity.hasInterationExampleSprite && !entity.hasInterationExampleView;
        }

        protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
        {
        //收集匹配的实体并且返回
                return context.CreateCollector(GameMatcher.InterationExampleSprite);
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Unity ECS(Entity Component System)是Unity引擎的一种编程范式,它是一种数据驱动的编程模型,它将游戏对象(Entity)分解为数据和行为两个部分,其中数据由组件(Component)来表示,行为则由系统(System)来实现。相对于传统的面向对象编程模型,ECS提供了更高效、更灵活的编程方式,可以有效地提高游戏的性能和扩展性。 下面是我学习Unity ECS时的笔记: ## Entity Entity是ECS中最基本的概念,它表示游戏对象。每个Entity由一个唯一的ID来标识,可以通过EntityManager来创建、销毁、查询和管理Entity。 ## Component Component是Entity的数据部分,用来描述Entity的属性和状态。每个Component包含一些数据成员和一些方法,用来操作这些数据成员。Component是以结构体(struct)的形式定义的,通常只包含数据成员,不包含方法。 ## System System是Entity的行为部分,用来实现游戏逻辑和操作Component。System可以访问和操作EntityManager和Component,但不能直接访问Entity。每个System包含一个或多个Component,表示它所处理的数据类型。System是以类(class)的形式定义的,通常包含一个Update方法,用来实现游戏逻辑。 ## Job Job是一种轻量级的线程,用于并行执行System中的任务。Job可以访问和操作Component,但不能直接访问Entity和EntityManager。Job通常是以结构体(struct)的形式定义的,不包含方法。 ## Archetype Archetype是Entity的集合,包含一组具有相同Component类型的Entity。Archetype可以用来优化数据的访问和处理,可以在不同的System之间共享。 ## Chunk Chunk是Archetype中的数据块,包含一组连续的Entity和它们的Component数据。Chunk可以用来优化内存的分配和访问,可以在Job中进行并行处理。 ## Buffer Buffer是一种Component类型,用来存储可变长度的数据,例如数组或列表。Buffer可以在System和Job中进行修改和访问。 以上是我学习Unity ECS时的笔记,希望对你有所帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值