编程
Fundamentals
Setting Up Development Environment
UnigineScript
High-Level Systems
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine and Tools
GUI
Double Precision Coordinates
应用程序接口
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
Rendering-Related Classes

添加脚本到项目中

要对您的项目进行编程,有一个最简单的方法就是使用UnigineScript语言(它无需编译)。

在本教程中我们会使用脚本来生成一个Primitive对象(以Box为例),并为它添加游戏逻辑让其旋转。

步骤1. 添加基本对象(Primitive Object)到虚拟世界中

  1. 通过SDK Browser运行(点击"Run")加载有Editor的项目。

  2. 在菜单栏上选择Create(创建) -> Primitive(基本对象) -> Box(盒体)创建Box对象。

  3. 在打开的Create Box(创建盒体)窗口中指定Box的大小并点击Ok(确定)按钮。

  4. 点击鼠标左键放置一个Box。

  5. 在菜单栏上点击Windows(窗口) -> Nodes(节点)或按N键打开Nodes(节点)窗口。

  6. 选择默认添加的节点并将其重命名为box。 同时将其Position(坐标位置)更改为0, 0, 1

  7. 在菜单栏上点击File(文件) -> Save world(保存世界)或按组合键CTRL + S保存虚拟世界。

步骤2. 添加脚本逻辑

有两种方法可以将脚本添加给对象:

方法1:通过编辑扩展名为.cpp的world(世界)脚本文件来添加

要想添加可旋转box的逻辑,您应使用纯文本编辑器修改名为<your_project_name>.cpp的world(世界)脚本文件。

注意
存放在data文件夹中的所有.cpp文件和.h文件都是UnigineScript脚本。 由于在引擎的Initialization(初始化)阶段,引擎自身会对这些脚本进行解释,所以它们是不需要被编译的。

  1. 通过SDK Browser打开项目文件夹。

  2. 使用纯文本编辑器打开存放在您文件夹路径data/<your_project_name>下的名为<your_project_name>.cpp的脚本文件。

    源代码 (UnigineScript)
    #include <core/unigine.h>
    
    int init() {
    	PlayerSpectator camera = new PlayerSpectator();
    	camera.setPosition(Vec3(2.0f,0.0f,1.5f));
    	camera.setDirection(Vec3(-1.0f,0.0f,-0.5f));
    	engine.game.setPlayer(camera);
    									
    	return 1;
    }
    
    int shutdown() {
    	return 1;
    }
    
    int update() {
    	return 1;
    }

    world(世界)脚本默认包含如下功能:

    • init()功能被用来在加载虚拟世界时创建对象以及初始化所有其它必要资源。
    • update()功能被用来编码项目逻辑,每帧都会执行该功能。
    • shutdown()功能被用来编码项目逻辑,虚拟世界被卸载时会执行该功能。

    init()功能中的如下这部分程序代码用来创建可与对象碰撞的,能自由飞行的新游戏摄像机(不过它不能被推移或与其它对象相互作用)。 点击跳转章节可了解更多引擎功能。

    源代码 (UnigineScript)
    // 创建一个新的观众(spectator)player
    PlayerSpectator camera = new PlayerSpectator();
    
    // 将其转动到指定方向
    camera.setPosition(Vec3(2.0f,0.0f,1.5f));
    
    // 将其放置在指定坐标点
    camera.setDirection(Vec3(-1.0f,0.0f,-0.5f));
    
    // 设置该player为默认摄像机
    engine.game.setPlayer(camera);
    注意
    添加的注释用于向您解释每行代码的作用。
  3. init()功能之前添加一个处理所需box节点的变量。
    警告
    我们【不推荐】您为自己的实际项目创建全局变量。
    源代码 (UnigineScript)
    Node box; // 添加box节点
    
    int init() {
    	/* ... */
    	}
  4. 将如下代码放进init()功能里来获取box节点。
    源代码 (UnigineScript)
    Node box; // 添加box节点	
    
    int init() {
    	/* ... */
    						
    	// 通过指定名称来搜索该节点
    	int index = engine.editor.findNode("box");
    								
    	// 通过节点自身的index(索引)来获取该节点
    	if(index != -1) {
    		box = engine.editor.getNode(index);
    	}
    									
    	return 1;
    }
    注意
    尽管节点可以由任意脚本(World,System或Editor)和Unigine Engine Editor(该编辑器可加载和存储world文件中的所有节点)来处理,但是它们只能由这四者之一所拥有。 否则,这样的节点就很有可能会导致引擎崩溃或内存泄露。
    具体可参阅Memory Management(内存管理)章节。
  5. update()循环中设置节点变换。 请注意,要想获得恒定的角速度,就必须使用帧时长来缩放每一帧的旋转角度(因为对每一单独帧而言其旋转角度都是不同的)。
    源代码 (UnigineScript)
    /* ... */
    
    int update() {
    
    	// 检查该节点是否存在
    	if(box != NULL) {
    											
    		// 获取帧时长
    		float ifps = engine.game.getIFps();
    											
    		// 设置旋转角度
    		float angle = ifps * 90.0f;
    											
    		// 获取该节点的当前变换并应用旋转
    		mat4 transform = box.getTransform() * rotateZ(angle);
    											
    		// 为该节点设置新变换
    		box.setTransform(transform);
    	}
    	return 1;
    }
    因此,最终的脚本如下:
    源代码 (UnigineScript)
    #include <core/unigine.h>
    						
    Node box; // 添加box节点
    							
    int init() {
    
    	// 创建一个新的观众(spectator)player
    	PlayerSpectator player = new PlayerSpectator();
    							
    	// 将其放置在指定坐标点
    	player.setPosition(vec3(3.5,0.0,1.3));
    							
    	// 将其转动到指定方向
    	player.setDirection(vec3(-1.0,0.0,-0.3));
    							
    	// 设置该player为默认摄像机
    	engine.game.setPlayer(player);
    							
    	// 通过指定名称来搜索该节点
    	int index = engine.editor.findNode("box");
    							
    	// 通过节点自身的index(索引)来获取该节点
    	if(index != -1) {
    		box = engine.editor.getNode(index);
    	}		
    	return 1;
    	}
    
    int shutdown() {
    	return 1;
    }
    
    int update() {
    
    	// 检查该节点是否存在
    	if(box != NULL) {
    								
    		// 获取帧时长
    		float ifps = engine.game.getIFps();
    								
    		// 设置旋转角度
    		float angle = ifps * 90.0f;
    								
    		// 获取该节点的当前变换并计算旋转
    		mat4 transform = box.getTransform() * rotateZ(angle);
    								
    		// 为该节点设置新变换
    		box.setTransform(transform);
    	}
    	return 1;
    }
  6. 将所有更改保存到名为<your_project_name>.cpp的world(世界)脚本文件中。
  7. 如果您已打开了自己的项目,就可以按重音符(`)键打开控制台,该键位于电脑键盘ESC键下方。

  8. 输入如下命令按Enter(回车)键观看结果。
    源代码
    world_reload

方法2:通过WorldExpression对象来添加

您还可以通过WorldExpression对象将脚本添加给Box(盒体)。

  1. 在菜单栏上选择Create(创建) -> World(世界) -> Expression(表达式),来创建一个WorldExpression(表达式)对象。

  2. 点击鼠标左键放置一个Box。

  3. 在菜单栏上点击Windows(窗口) -> Nodes(节点)或按N键打开Nodes(节点)窗口。

  4. 选择默认添加的WorldExpression节点并将其Position(坐标位置)更改为1, -1, 0.5。 到此,在平面上就给出了一个基本Box对象和一个World Expression(表达式)对象。

  5. 选择WorldExpression节点并打开Expression(表达式) 标签页。

  6. 将程序代码放置在Source(源代码)区域。
    源代码 (UnigineScript)
    {
    	// 通过WorldExpression节点自身的内部功能来获取该节点
    	Node worldExpression = getNode();
    	
    	// 获取帧时长
    	float ifps = engine.game.getIFps();
    
    	// 设置旋转角度
    	float angle = ifps * 90.0f;
    
    	// 获取该节点的当前变换并应用旋转
    	mat4 transform = worldExpression.getTransform() * rotateZ(angle);
    
    	// 为该节点设置新变换
    	worldExpression.setTransform(transform);
    }
    警告
    在此处必须要使用花括号将程序代码括起来!

    您可以点击此跳转章节了解将脚本添加给World Expression(表达式)对象的其它方法。

  7. 按住ALT键的同时拖动box节点到Nodes(节点)层级列表中的worldExpression节点下。

    现在,box对象就成为了worldExpression对象的子对象。 这也意味着box对象继承了World Expression(表达式)对象的所有表达式变换。
    注意
    成为World Expression(表达式)对象的子对象的所有对象都会继承它的表达式变换。
    如果box节点落在了Viewing Frustum(视锥体)外部,但是其包围盒仍然处于视锥体内部,或是摄像机处于该包围盒之内,那么变换序列的回放也将会继续进行。
  8. 关闭Nodes(节点)窗口观看结果。

最新更新: 2017-07-03