【发布时间】:2017-08-02 08:44:35
【问题描述】:
我在暑假期间将游戏引擎作为一个项目进行工作。每个可编写脚本的组件都应该可以访问它们所在场景中的某些方法。为了实现这一点,我将调用相应方法的场景中的 lambdas 传递给可编写脚本的组件,在这些组件中它们被隐式转换为 std::function 类型。
场景.h:
class Scene
{
private:
unsigned int _currentId;
std::vector<System*> _systems;
//SCRIPTABLE NEEDS THE BELOW METHODS THESE EXCLUSIVELY:
bool exists(unsigned id);
void destroy(unsigned int);
void addComponent(Component*, unsigned int);
template<typename T> T& getComponent(unsigned int);
template<typename T> bool hasComponent(unsigned int);
template<typename T> void removeComponent(unsigned int);
protected:
unsigned int instantiate(std::vector<Component*>);
public:
Scene(ChangeSceneCallback);
~Scene();
void initiate();
void update(long dt);
};
template<typename T>
inline T & Scene::getComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return static_cast<T*>(system->getComponent(entityId));
}
}
}
template<typename T>
inline bool Scene::hasComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return system->contains(id);
}
}
}
template<typename T>
inline void Scene::removeComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return system->destroy(id);
}
}
}
回调方法适用于我需要访问的非模板函数,但不适用于模板函数,所以它是不可能的。
可编写脚本:
typedef std::function<void(int)> ChangeSceneCallback;
typedef std::function<int(std::vector<Component*>)> InstantiateCallback;
typedef std::function<void(int)> DestroyCallback;
typedef std::function<bool(int)> ExistCallback;
typedef std::function<void(Component*, unsigned int)> AddComponentCallback;
class Scriptable: public Component
{
protected:
ChangeSceneCallback changeScene;
InstantiateCallback instantiate;
DestroyCallback destroy;
ExistCallback exists;
public:
~Scriptable();
Scriptable();
void assignCallbacks(ChangeSceneCallback, InstantiateCallback etc ...);
virtual void init() = 0;
virtual void update() = 0;
};
Scriptable 无法访问场景中的公共方法,因为这将使用户/开发人员能够访问它们(Scriptable 是游戏行为的基类)。这就是为什么我需要想出一些东西来让脚本有限地访问场景。
有什么想法吗?
【问题讨论】:
-
没有指向模板函数的指针。它需要运行时代码编译。
-
这个问题毫无意义。只要模板参数不固定(特化),模板就是模板。它不是类型,也不是函数。您可以定义模板 typedef(使用 C++11 功能),但这仍然不允许您在不指定模板参数的情况下将其用作类型。
-
您介意解释一下
system->corresponds(T)的含义吗? -
而
using通常比typedef更具可读性,using是模板所必需的:template<typename T> using GetComponentCallback = std::function<T&(unsigned int)>;。但这仍然需要为std::function<MyComponent&(unsigned int)>使用GetComponentCallback<MyComponent>之类的东西 -
@ojoj kolol:“回调”是当今 C++ 中一个相当广泛的概念。这取决于您所说的“回调”是什么意思。如果您希望将回调目标存储在
std::function中,那么您必须首先专门化目标模板,即为所有模板参数指定具体参数(之后它将不再是模板)。
标签: c++ templates callback game-engine