(转)我所理解的Entitas——Entity Context(二)

发布时间 2023-06-13 15:26:23作者: 星月相随

这章我们将介绍ECS的三大基本概念种的Entity,同时Entity又和Context息息相关

 

Entity 实体
实体作为ECS的三大基本概念之一,实体作为组件的载体,本身并无实际意义,最核心的数据便是唯一ID,和Untiy的GameObject类似。在游戏世界中可以被创建,被销毁,可以添加组件,删除组件。

实体初始化
Entitas中的实体只能由Context的CreateEntity()方法创建。可以大概看下源码:

    //判断对象池是否有空闲对象
    if (_reusableEntities.Count > 0) {
        entity = _reusableEntities.Pop();
        //如果有,则拿出来,同时赋予新的ID
        entity.Reactivate(_creationIndex++);
    } else {
        //如果没有,则创建,并且初始化
        entity = _entityFactory();
        entity.Initialize(_creationIndex++, _totalComponents, _componentPools,_contextInfo, _aercFactory(entity));
    }

实体的销毁

实体销毁是调用Destroy()方法,但是这个方法并不是真正执行销毁逻辑,Context内部提供了用来管理Entity的对象池,调用Destroy()方法时只是将实体身上的组件,委托事件等移除然后放入对象池等待下次使用:

public void Destroy() {
    if (!_isEnabled) {
        throw new EntityIsNotEnabledException("Cannot destroy " + this + "!");
    }
    if (OnDestroyEntity != null) {
        OnDestroyEntity(this);
    }
}

public void InternalDestroy() {
    _isEnabled = false;
    RemoveAllComponents();
    OnComponentAdded = null;
    OnComponentReplaced = null;
    OnComponentRemoved = null;
    OnDestroyEntity = null;
}

 

Context 上下文

Context是Entity的上下文环境,用来管理当前环境下的所有Entity和Group的创建和回收。可以同时存在多个Context,Entitas默认会生成两个Context,分别是Game,Input。可以在Jenny的设置面板修改Context。

 

注意:设置面板中的第一个Context将会被作为默认的,会对之后生成组件产生影响,之后详细讲解。

生成的Context代码存放在Generated文件夹下。

 

在生成Context时同时会生成Lookup类和一个Matcher类

  • Lookup 用来管理当前Context的所有组件组件信息。
public static class InputComponentsLookup {

        public const int MyNameSpaceTestComponent = 0;
        public const int TestTwo = 1;

        public const int TotalComponents = 2;

        public static readonly string[] componentNames = {
            "MyNameSpaceTestComponent",
            "TestTwo"
        };

        public static readonly System.Type[] componentTypes = {
            typeof(MyNameSpace.TestComponentComponent),
            typeof(TestTwoComponent)
        };
    }
  • Matcher 用来定义当前Context中的实体的筛选条件
public sealed partial class InputMatcher {

    public static Entitas.IAllOfMatcher<InputEntity> AllOf(params int[] indices) {
        return Entitas.Matcher<InputEntity>.AllOf(indices);
    }

    public static Entitas.IAllOfMatcher<InputEntity> AllOf(params Entitas.IMatcher<InputEntity>[] matchers) {
          return Entitas.Matcher<InputEntity>.AllOf(matchers);
    }

    public static Entitas.IAnyOfMatcher<InputEntity> AnyOf(params int[] indices) {
          return Entitas.Matcher<InputEntity>.AnyOf(indices);
    }

    public static Entitas.IAnyOfMatcher<InputEntity> AnyOf(params Entitas.IMatcher<InputEntity>[] matchers) {
          return Entitas.Matcher<InputEntity>.AnyOf(matchers);
    }
}

同时存在的多个Context每个之间互不影响。所有的Context由Contexts管理。

 

Contexts

Contexts是个单例。通过Contexts.sharedInstance访问,内部持有所有Context的引用。是由Entitas代码生成器生成,无需手动实现也不能够手动实现。

public partial class Contexts : Entitas.IContexts {
        public static Contexts sharedInstance {
            get {
                if (_sharedInstance == null) {
                    _sharedInstance = new Contexts();
                }
                return _sharedInstance;
            }
            set { _sharedInstance = value; }
        }
        
        static Contexts _sharedInstance;
        
        public GameContext game { get; set; }
        
        public InputContext input { get; set; }
        
        public Entitas.IContext[] allContexts { get { return new Entitas.IContext [] { game, input }; } }

        public Contexts() {
            game = new GameContext();
            input = new InputContext();
        }
    }

总结:
游戏世界中的Contexts可以理解为一个军区司令。
军区司令管理着多个军种:陆军(context_1),海军(context_2),空军(context_3)。
每个军种又管这着具体的每为士兵(Entity)。

 

原文地址:https://blog.csdn.net/u010020342/article/details/109898547?spm=1001.2014.3001.5502