这章我们将介绍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)。