2017-07-26 75 views
2

我正在使用ECS的遊戲引擎。我的問題是我如何生成一個實體。我的想法是,我有一個發生在一個實體作爲參數的方法,創建這個實體的克隆,從克隆retrives所有指針組件並把它們在各自的系統更新:遊戲引擎設計問題

Entity & Scene::spawnEntity(Entity entity) { 

    Entity clone = Entity(entity); 

    Transform* transform = clone.getComponent<Transform>(); 
    Drawable* drawable = clone.getComponent<Drawable>(); 
    Collidable* collidable = clone.getComponent<Collidable>(); 
    Scriptable* scriptable = clone.getComponent<Scriptable>(); 

    if (transform != nullptr) { 
     _transformSystem.add(*transform, _currentId); 
    } 
    if (drawable != nullptr) { 
     _drawableSystem.add(*drawable, _currentId); 
    } 
    if (collidable != nullptr) { 
     _collidableSystem.add(*collidable, _currentId); 
    } 
    if (scriptable != nullptr) { 
     scriptable->assignCallbacks([&](Entity entity)        -> Entity&    { spawnEntity(entity); }, 
            [&](Entity entity)              { destroyEntity(entity); }, 
            [&](std::vector<std::string> tags)    -> Entity&    { findEntity(tags); }, 
            [&](std::vector<std::vector<std::string>> tags) -> std::vector<Entity>& { findEntities(tags); }); 
     _scriptableSystem.add(scriptable, _currentId); 
    } 

    _entities.push_back(clone); 

    _currentId++; 
} 

的問題在於,其中一個組件,即腳本是純粹的抽象類(它具有開發方法和更新方法,開發人員用它在派生類中創建行爲)。這就使發動機不能自動克隆編寫腳本類,克隆在派生類中完成,例如像這樣:

class PlayerScript : public Scriptable 
{ 
public: 
    void init() override; 
    void update() override; 
    PlayerScript* clone() override; 
}; 


PlayerScript * PlayerScript::clone() 
{ 
    return new PlayerScript(*this); 
} 

我不希望用戶必須創建一個克隆方法每個腳本他或她創建,我認爲它應該由引擎自動處理。但我不知道如何做不同。

回答

2

只要玩家的腳本是拷貝構造,你可以通過拷貝構造函數的方法克隆它們,你可以使用CRTP和這樣一箇中間類(最小,工作爲例):

struct BaseScriptable { 
    virtual ~BaseScriptable() = default; 
    virtual BaseScriptable * clone() = 0; 
    virtual void update() = 0; 
}; 

template<typename D> 
struct Scriptable: BaseScriptable { 
    BaseScriptable * clone() override final { 
     return new D{*static_cast<D *>(this)}; 
    } 
}; 

struct PlayerScript: Scriptable<PlayerScript> { 
    void update() override {} 
}; 

int main() { 
    BaseScriptable *script = new PlayerScript; 
    BaseScriptable *clone = script->clone(); 
} 

如果複製構造函數不足以克隆播放器腳本,這意味着您沒有足夠的信息來實際克隆它。因此,定義腳本的開發人員必須定義一個克隆例程,以便爲您提供正確的副本。