Treasure / EntityManager

Created Sat, 01 Apr 2023 00:00:00 +0000
886 Words

EntityManager是一个很重要的模块,像游戏开发本身就是视觉感知,而EntityManager是对所有场景物体的统一抽象封装, 并提供一系列通用操作,EntityManager 本身是一个抽象类,提供了一定程度的通用性操作,但针对一些特殊情况我们还是需要针对特定问题特定实现(千万不想要想着做平,来自某家公司的教训:))

EntityManager 附带一个默认的 EntityController,提供一些常规的实体控制,像 Zen的UI框架就是基于 EntityManager的一个具体实现。

Entity

抽象描述一个物体的实体,它的生命周期函数定义类似于GameComponent,但是它的调度不由GameEntry而是 GameComponent

简单来说,要创建一个物体首先我们需要定义它的逻辑模板(骨架)以及它的数据(描述)

举个例子


public struct EnemyData:IEntityData{
    // 对于实体数据接口,资源名必不可少
    public string Assets {get;set;}


    public void OnCtor(){
        // 有些时候,实体的数据更关卡等级或这地图这类外部数据挂钩,可能需要在这里动态设置一次
    }
}

// 定义Entity的逻辑模板
public struct Enemy:Entity {

    protected EnemyData userdata;

    protected void OnCtor(){
        // init setup...
    }     

    protected void OnUpdate(float delta,float unscaleDelta){
        // loop logic.
    }
}


void dosomething(){
    // 直接在默认的EntityManager中创建一个实体
    GameEntry.GetComponent<EntityManager>().Load<Enemy>(new EnemyData());
}

对于实体的销毁,像敌人死亡,特效消失之类的,仅仅只需要设置一个 Alive 属性,即可完成,生命周期由EntityManger自行决断。

需要注意的是 继承IEntityData的数据模板是会一直复用的,它与 Entity的复用规则不同,后者复用的是Entity所持有的实体,因为它本身只是一系列函数集合且很少会带有数据并不会占用太多的内存,而前者大部分情况下是都是通过读表获取,复杂的实体数据可能会导致内存异常大,所以保留实体数据是EntityManager的默认行为。

EntitySettings

EntityManager可能需要在某些大量对象时使用对象池(Entity),或者内存池(EntityData),但在大多数情况下,框架并不清楚是否需要对象池,或者是需要一个定长周期的物体(子弹或者特效)。

这个时候需要设置就非常有必要了,可以决断出是否需要且生命周期(keepalive)或者是需要多大的对象池,以及自动孵化的频率了。