Editor(编辑器)插件
Game Framework Editor(游戏框架编辑器)能使您在Unigine Editor中正确创建游戏。
Game Framework Editor中有3个主要区域:
- New Game(新建游戏) - 创建新游戏
- Open Game(打开游戏) - 打开游戏
- Save Game(保存游戏) - 保存当前游戏
- Play Level(播放关卡) - 播放关卡
- Settings(设置) - 打开设置窗口
关卡(Levels)
其代表的是罗列的关卡以及对这些关卡所进行的操作:
- New Level(新建关卡) - 创建新关卡
- Remove Level(移除关卡) - 删除所选关卡
实体(Entities)
其代表的是罗列的实体以及对这些实体所进行的操作:
- New Entity(新建实体) - 创建新实体
- Remove Entity(移除实体) - 删除所选实体
- Assign Entity(分配实体) - 将实体分配给节点引用或节点
Info
其作用是显示所选元素的信息。
创建游戏(Game)
要想创建新游戏,须点击New Game(新建游戏)按钮。 这时,游戏创建的对话框窗口将被打开:
- Name(名称) - 指游戏的名称。 它可以包含任意字符或者干脆为空。 其默认值为new_game。
- File(文件) - 指*.game文件的路径名称(相对于data目录的路径),该文件包含了有关游戏(game),关卡(levels),实体(entities)的所有信息,也包含了游戏和Editor的所有附加参数。 其默认值为games/new_game/new_game.game。
- Entity(实体) - 指*.prop文件的路径名称(相对于data目录的路径),该文件包含了有关基本实体(Entity)的所有信息。 它会由Editor自动生成。 其默认值为games/new_game/entity.prop。
- Property List(属性列表) - 指*.prop_list文件的路径名称(相对于data目录的路径),该文件罗列出了所有的游戏属性。 它会由Editor自动生成。 其默认值为games/new_game/properties.prop_list。
如果您将选项栏中的某一个给填错了,那警告图标就会出现。 当您将鼠标悬停在该图标上时,就会显示警告信息。
如果所有的选项栏都填写正确,在点击完Create(创建)按钮之后,游戏和所有的附加文件就会被创建。 而游戏也将被Editor瞬间打开。 所有这些设置在以后都可以更改。
编辑游戏(Game)
通过点击Open(打开)按钮打开要进行编辑的游戏。 在标题栏上可以看到*.game文件的目录。 Game的设置可以在Editor的Settings窗口(Game framework settings/Game settings/Game)中更改:
- Name(名称) - 指游戏的名称(可选项)
- Developer(开发者) - 指游戏的开发者(可选项)
- Version(版本) - 指游戏的版本(可选项)
- Copyright(版权) - 指版权(可选项)
- Window Title(窗口标题) - 指游戏被加载时窗口的标题(默认留空)
- Description(描述) - 指游戏的描述(可选项)
- Entity Property(实体属性) - 指*.prop文件的路径名称(相对于data目录的路径),该文件包含了有关基本实体(Entity)的所有信息。 它会由Editor自动生成。 其默认值为games/new_game/entity.prop。
如果您更改了该文件的名称或目录,那它就会被重命名以及被自动重新定位,不过它具有默认值。
- Property List(属性列表) - 一个*.prop_list文件。 指属性列表的路径名称(相对于data目录的路径),该文件罗列出了所有的游戏属性。 它会由Editor自动生成。 其默认值为games/new_game/properties.prop_list。
如果您更改了该文件的名称或目录,那它就会被重命名以及被自动重新定位,不过它具有默认值。
您可从Game launch选项栏更改游戏加载的相关设置(Settings/Game/Game Launch):
- System script(系统脚本) - 指system(系统)脚本的路径名称,该型脚本是启动游戏所必需的。 引擎为框架提供了默认的system(系统)脚本,它存放在路径下文件data/framework/game/game_system_script.cpp中。
- Extern Define(外部定义) - 指外部定义的列表(例如,如果您是用作移动平台开发的,就要使用RENDER_SIMPLE来定义)
- Extern Plugin(外部插件) - 指用户C++插件的列表
所有的游戏更改都应通过点击Save Game(保存游戏)按钮来保存。
创建关卡(Level)
要想创建新关卡,须点击New Level(新建关卡)按钮。 这时,关卡创建的对话框窗口将被打开:
General(一般)
- Name - 指关卡的名称。
- %name - 指相对的关卡名称,其会被自动设置为*.level文件,*.world文件和*.h文件的名称。
- Level File - 指*.level文件的路径名称(相对于data目录的路径),该文件包含了有关关卡的所有信息。
World(世界)
- File - 指新关卡的*.world文件的路径名称(相对于data目录的路径)。 如果*.world文件之前还未被创建,那它就将通过路径下文件data/framework/plugin/editor/templates/level/template.world中存放的模型来进行自动创建。
Logic(逻辑)
- Use Custom Logic - 指要使用自定义逻辑。 如果禁用了该参数,就会使用标准的框架关卡逻辑;否则,用来指定自定义逻辑的附加选项栏Logic Class和Logic File将被激活。
- Logic Class - 指类的名称,在关卡加载时该类的实例将被创建。
- Logic File - 指*.h文件的路径名称(相对于data目录的路径),该文件包含了关卡逻辑。
如果具有指定名称的该文件不存在,那它就将基于标准模型(存放在路径下文件data/framework/plugin/editor/templates/level/logic.h中)来进行自动创建,该模型是从基本的关卡逻辑类Level继承而来。
如果您想要更改关卡创建的自动填写参数,须打开Editor的Settings窗口(Game framework settings/Game settings/File Path Settings For New Levels):
引擎会为如下文件自动设置指定目录:
- Level (*.level) - 指*.level文件的路径名称
- Logic (*.h) - 指带有关卡逻辑的*.h文件的路径名称
- World (*.world) - 指*.world文件的路径名称
如果您将选项栏中的某一个给填错了,那警告图标就会出现。 当您将鼠标悬停在该图标上时,就会显示警告信息。
如果所有的选项栏都填写正确,在点击完Create(创建)按钮之后,关卡文件和所有的附加文件就会被创建。 而关卡也将Editor打开。 所有这些设置在以后都可以更改。
编辑关卡(Level)
当关卡被选中之后,就可以在Level(关卡)标签页内对它进行编辑:
- Name - 指关卡的名称
- World - 指新关卡的*.world文件的路径名称(相对于data目录的路径)。
- Logic - 指*.h文件的路径名称(相对于data目录的路径),该文件包含了关卡逻辑。 如果具有指定名称的该文件不存在,那它就将基于标准模型(存放在路径下文件data/framework/plugin/editor/templates/level/logic.h中)来进行自动创建,该模型是从基本的关卡逻辑类Level继承而来。
- Logic class - 指类的名称,在关卡加载时该类的实例将被创建。
>所有的游戏更改都应通过点击Save Game(保存游戏)按钮来保存。
要想加载或重新加载某个虚拟世界,只需双击关卡列表中的关卡即可,这样,Editor就会生成并重新加载所有的属性,也会为您的关卡加载所需的虚拟世界,如此一来您就能对它进行编辑,参数更改,添加,删除或编辑节点的操作了。 已加载的关卡会以蓝色来高亮显示。
当适用某个关卡的虚拟世界在Editor中被加载了之后,Play level(播放关卡)按钮会在运行时(rumtime)中变为可用,换句话说,游戏被启动了。 Play level(播放关卡)按钮会为要启动的游戏在运行时(runtime)中加载不止一个引擎的实例。
您可从Editor的关卡播放选项窗口更改关卡加载的相关设置(Game framework settings/Editor settings/Play level options):
- Binary - 用来指定播放关卡时要加载的二进制文件
- Debug - 用来指定是否启用debug模式
- Video API - 指视频API切换器。 可设置的值有:
- OpenGL - OpenGL API(适用Windows,OS和Linux系统)
- Direct3D9 - Direct3D9 API(适用Windows系统)
- Direct3D11 - Direct3D11 API(适用Windows系统)
- Resolution - 指引擎窗口的分辨率
- VSync - 指垂直同步
- Fullscreen - 指全屏模式
- Engine Config - 指引擎的配置文件
- Engine Log - 指引擎的日志文件
- Editor Config - 指Editor的配置文件
自定义关卡逻辑
自定义逻辑可被应用给游戏中的所有关卡。 它可以是每个关卡独有的,又或是所有关卡都通用的。
要想游戏能正确运行,逻辑文件就应该从基本的框架关卡类继承。 该类存放在路径下文件data/framework/game/level.h中。
如果用户代码不正确,游戏就不能被加载。 而相应的警告消息也会出现在控制台和日志文件中。
您可通过点击Logic选项栏旁边的Edit Logic(编辑逻辑)按钮来快速访问逻辑文件。 默认情况下,带有指定逻辑的文件夹将被打开。 您可在Editor标签页内的Open Cmd File(打开Cmd文件)选项栏中指定逻辑文件的名称,这样,文件自身就会在点击Edit Logic(编辑逻辑)按钮时被打开:
自定义逻辑的用法举例:
#ifndef _MYLEVEL_H_
#define _MYLEVEL_H_
/******************************************************************************\
*
* class MyLevel
*
\******************************************************************************/
class MyLevel : Level {
private:
int first_update = true;
public:
MyLevel() {
log.message(“MyLevel constructor called\n”);
}
~MyLevel() {
log.message(“MyLevel desstructor called\n”);
}
// 在所有实体(entities)创建之前调用该函数
void onWarm() {
// 在此放置您的警告代码
log.message(“MyLevel onWarm() called\n”);
}
// 在所有实体(entities)创建之后调用该函数
void onInit() {
// 在此放置您的init代码
log.message(“MyLevel onInit() called\n”);
}
void onShutdown() {
// 在此放置您的shutdown代码
log.message(“MyLevel onSutdown() called\n”);
}
void onPreUpdate() {
// 实体(entities)更新之前调用
// 在此放置您的update代码
}
void onPostUpdate() {
// 实体(entities)更新之后调用
// 在此放置您的update代码
if(first_update) {
log.message(“MyLevel onPostUpdate() called\n”);
first_update = false;
}
}
void onRender() {
// 在此放置您的render代码
}
void onFlush() {
// 在此放置您的flush代码
}
};
#endif /* _MYLEVEL_H_ */
类的实例将会在关卡加载时由游戏自动创建,所有的函数也都会以适当的顺序被调用。
您可创建属于您自己的基类,该基类被从框架关卡类继承,而后从它继承您的其它类。 为此,只需在您的关卡逻辑文件中包含基类文件的文件头即可:
#ifndef _MYLEVEL_0_H_
#define _MYLEVEL_0_H_
#include <data/....my_project_path.../scripts/my_level.h>
/******************************************************************************\
*
* class MyLevel_0
*
\******************************************************************************/
class MyLevel_0 : MyLevel {
private:
public:
onInit() {
super.onInit();
log.message(“my custom logic init\n”);
}
};
#endif /* _MYLEVEL_0_H_ */
创建实体(Entity)
要想创建新实体,须点击New Entity(新建实体)按钮。 这时,实体创建的对话框窗口将被打开:
General(一般)
- Name - 指实体名称,其会将名称赋予给对应的实体类和属性。
- %name - 指相对的实体名称,其会被自动设置为*.entity文件,*.h文件,*.prop文件和*.node文件的名称。
- File - 指*.entity文件的路径名称(相对于data目录的路径),该文件包含了有关实体的所有信息。
Logic(逻辑)
- Parent - 指基本实体的名称,新实体及其属性的实例都是从该基本实体继承而来。
- File - 指*.h文件的路径名称(相对于data目录的路径),该文件包含了实体逻辑。
如果具有指定名称的该文件不存在,那它就将基于标准模型(存放在路径下文件data/framework/plugin/editor/templates/entity/logic.h中)来进行自动创建,该模型是从基本的实体类Entity继承而来。
- Property - 指*.prop文件的路径名称(相对于data目录的路径),该文件包含了属性信息。 如果具有指定名称的该文件不存在,那它就会被自动创建。
Node(节点)
- Use Node - 用来指定是否使用已分配的节点来创建实体。 如果禁用了该参数,那新实体就会在不使用任何已分配节点的情况下被创建,这样,当您在节点层级中选中它时,它就没有Node(节点)标签页。 在将这样的一个实体放进虚拟世界中(通过拖拽操作)时,分配有该实体的伪节点就会出现。 与其它类型的节点一样,伪节点也能被分配属性。
对于未分配实体的节点而言,它们拥有相同的update逻辑和shutdown逻辑(指onInit(),onUpdate(),onFlush(),onRender()和onShutdown()这几个函数的调用),不过,它们实体初始化的逻辑是不同的。 如果实体被分配给了节点引用,那该实体的类的实例就会由Node::setVariable方法放进根节点中;但是如果实体是被分配给节点的,那类的实例将不会被放在任何地方,它也不能从节点获得。 不过,您却可以通过onInit()函数来手动获取它。 让我们举个例子来说明:假设将被称为MyEntity的一个空(未分配节点)实体分配给了带有复杂层级的节点。 我们知道,作为子节点,它会拥有一个被称为"my_mesh"的mesh(网格),而该mesh则可由相交(intersection)方法获得。 如果作为变量的指定类的实例会由此mesh获取,那我们就能从该节点获得指定实体的类的实例:
class MyEntity : Entity { private: ObjectMesh my_mesh; public: void onInit() { my_mesh = getNode(“my_mesh”); my_mesh.setVariable(this); } void onShutdown() { my_mesh.setVariable(NULL); } };
如果您通过Node::setVariable()方法设置了实体或其它逻辑类,那您就需要在shutdown()阶段调用Node::setVariable(NULL)方法。 - Node File - 指新实体的*.node文件的路径名称(相对于data目录的路径)。
如果*.node文件之前还未被创建,那它就将通过路径下文件data/framework/plugin/editor/templates/entity/template.node中存放的模型来进行自动创建。
如果您想要更改实体创建的自动填写参数,须打开Editor的Settings窗口(Settings/Game/File Path Settings For New Entities):
引擎会为如下文件自动设置指定目录:
- Entity (*.entity) - 指*.entity文件的路径名称
- Logic (*.h) - 指带有实体逻辑的*.h文件的路径名称
- Node (*.node) - 指*.node文件的路径名称
- Property (*.property) - 指*.prop文件的路径名称
如果您将选项栏中的某一个给填错了,那警告图标就会出现。 当您将鼠标悬停在该图标上时,就会显示警告信息。
如果所有的选项栏都填写正确,在点击完Create(创建)按钮之后,实体文件和所有的附加文件就会被创建。 所有这些设置在以后都可以更改。
编辑实体(Entity)
当实体被选中之后,就可以在Entity(实体)标签页和Fields(字段)标签页内对它进行编辑:
- Name - 指实体的名称。
- Parent - 指基本实体的名称,新实体及其属性的实例都是从该基本实体继承而来。
- Node - 指*.node文件的路径名称。
- Logic - 指*.h文件的路径名称(相对于data目录的路径),该文件包含了实体逻辑。
如果具有指定名称的该文件不存在,那它就将基于标准模型(存放在路径下文件data/framework/plugin/editor/templates/entity/logic.h中)来进行自动创建,该模型是从基本的实体类Entity继承而来。
- Property - 指*.prop文件的路径名称(相对于data目录的路径),该文件包含了属性信息。
如果具有指定名称的该文件不存在,如果具有指定名称的该文件不存在,那它就会被自动创建。
- 描述 - 指实体的自定义描述。
- Init order - 用来定义实体(entities)初始化的顺序。 该字段仅适用关卡初始化和被放进虚拟世界的实体。 它对动态创建的实体无影响。
- Enabled - 用来指明是否启用实体及其节点引用。
- Rendereable - 用来指明onRender()方法是否供该实体调用。
- Flushable - 用来指明onFlush()方法是否供该实体调用。
- Updateable - 用来指明onUpdate()方法是否供该实体调用。
- Update order - 用来定义调用onRender(),onFlush()和onUpdate()这几种方法的顺序。
每次游戏被加载或关卡被加载时,实体列表都会被依照用户类中类的层级自动生成 。 为使Editor能正确加载游戏并生成实体列表,就必须编译用户代码。 如果用户代码还未被编译,那游戏将不能被加载,而相应的警告消息也会出现在控制台和日志文件中。
要想将实体的实例放进关卡,只需将其从列表拖出并将其拽进已加载的关卡即可。 分配有属性的节点引用会被自动添加给Editor:
还有另一种将实体添加进关卡的方法:
- 在Unigine Editor中选择节点引用。
- 在Game Framework Editor(游戏框架编辑器)中选中实体并点击Assign Entity(分配实体)按钮。
这样,实体的属性就被分配给了节点引用,而该节点引用也就变成了实体。
所有的实体都用蓝色框框出了:
自定义实体逻辑
实体的层级构建以及属性的生成都基于动态编译的用户代码。
如前所述,Fields(字段)代表着实体的属性或自定义设置。 它们都是基于用户代码的属性特征(attributes)被自动生成的,并且这些字段也会依照实体的层级进行分组。
自定义实体的例子:
#ifndef _MYENTITY_H_
#define _MYENTITY_H_
/******************************************************************************\
*
* class MyEntity
*
\******************************************************************************/
class MyEntity : Entity {
private:
float rotate_speed = 15.0f;
float angle = 0.0f;
public:
MyEntity() {
}
~MyEntity() {
}
void onInit() {
// 在此放置您的init代码
}
void onShutdown() {
// 在此放置您的shutdown代码
}
void onUpdate() {
// 在此放置您的update代码
// 只是旋转节点
angle += rotate_speed * game.getGameIFps();
setRotation(quat(0.0f,0.0f,1.0f,angle));
}
void onRender() {
// 在此放置您的render代码
}
void onFlush() {
// 在此放置您的flush代码
}
};
#endif /* _MYENTITY_H_ */
上例向您展示了速度等于rotate_speed值的节点旋转的算法。 要想在框架编辑器中正确更改该速度,您就可以使用Fields(字段)。 只需为Editor中显示的参数添加具有特殊的属性特征(attributes)的setter方法和getter方法即可:
#ifndef _NEWENTITY_H_
#define _NEWENTITY_H_
/******************************************************************************\
*
* class NewEntity
*
\******************************************************************************/
class NewEntity : Entity {
private:
float rotate_speed = 15.0f;
float angle = 0.0f;
public:
NewEntity() {
}
~NewEntity() {
}
void onInit() {
// 在此放置您的init代码
}
void onShutdown() {
// 在此放置您的shutdown代码
}
void onUpdate() {
// 在此放置您的update代码
}
void onRender() {
// 在此放置您的render代码
}
void onFlush() {
// 在此放置您的flush代码
}
[get_float:Rotation Speed]
float getRotateSpeed() {
return rotate_speed;
}
[set_float:Rotation Speed]
void setRotateSpeed(float value) {
rotate_speed = value;
}
};
#endif /* _NEWENTITY_H_ */
待关卡重启完之后,在Fields(字段)标签页内就会出现一个新的float型字段Rotation Speed(旋转速度):
待实体(entity)的实例被添加给虚拟世界之后,其属性也将能在Nodes(节点)面板中进行调节。 这些属性位于所选实体(节点引用)的Fields(字段)标签页内: