This page has been translated automatically.
UNIGINE 基础课程
1. 简介
2. 虚拟世界管理
3. 3D模型准备
4. 材质
5. 摄像机和光照系统
7. 制作过场动画与动画序列
8. 准备发布项目
9. 物理系统
10. 优化基础
11. 项目2:第一人称射击游戏
12. PROJECT3: Third-Person Cross-Country Arcade Racing Game
13. PROJECT4: VR Application With Simple Interaction

物体移动与旋转

The objects existing in the virtual world are often moving somewhere and rotating, in general, transforming. Each node has a transformation matrix that encodes its position, rotation, and scale in the world. If a node is a child of another node (part of its hierarchy), it has a transformation matrix associated with the parent (local). This is why the Node class has two different properties: Transform and WorldTransform, which handle local and world transformation matrices respectively.虚拟世界中的物体经常需要进行移动、旋转等变换操作。每个节点都拥有一个变换矩阵,用于记录其在世界中的位置、旋转和缩放比例。当节点作为子节点存在时(属于某个父节点层级),它将拥有一个相对于父节点的局部变换矩阵。因此,Node类提供了两种不同的属性:Transform(局部变换)和WorldTransform(世界变换),分别处理局部和世界坐标系的变换矩阵。

The following code shows how basic node transformations are performed:以下代码展示了基本的节点变换操作实现方式:

源代码 (C++)
// 将Unigine命名空间注入全局命名空间
using namespace Unigine;
using namespace Unigine::Math;

// 沿X/Y/Z轴移动指定距离
node->setWorldPosition(node->getWorldPosition() + Vec3(X, Y, Z));

// 沿Y轴移动1个单位
node->worldTranslate(0.0f, 1.0f, 0.0f);

// 绕(X,Y,Z)轴旋转Alpha角度 
node->setWorldRotation(node->getWorldRotation() * quat(Vec3(X, Y, Z), Alpha));

// 绕X/Y/Z轴分别旋转指定角度 (angle_X, angle_Y, angle_Z)
node->setWorldRotation(node->getWorldRotation() * quat(angle_X, angle_Y, angle_Z));

// 绕Z轴旋转45度
node->worldRotate(0.0f, 0.0f, 45.0f);

// 使用方向向量和上向量设置节点朝向
node->setWorldDirection(vec3(0.5f, 0.5f, 0.0f), vec3_up, AXIS_Y);

// 设置节点沿各轴的缩放比例
node->setWorldScale(vec3(Scale_X, Scale_Y, Scale_Z));

// 创建复合变换矩阵:整体缩放2倍 + Z轴旋转45度 + 各轴平移1单位
Mat4 transform = Mat4(translate(vec3(1.0f, 1.0f, 1.0f)) * rotate(quat(0.0f, 0.0f, 1.0f, 45.0f)) * scale(vec3(2.0f)));

// 设置相对于父节点的变换矩阵
node->setTransform(transform);

// 设置相对于世界原点的变换矩阵
node->setWorldTransform(transform);

Practice
实践#

Let's add a fan to our scene and try to breathe life into it:让我们为场景添加风扇并实现动态旋转效果:

  1. Open the archviz/interior/fan folder in the Asset Browser, drag the fan asset fan.fbx to the scene and place it on the table near the bed.在资源浏览器中导航至 archviz/interior/fan 目录并将 fan.fbx 模型拖拽至场景,精确定位于床头桌面上。
  2. Open the archviz/interior/fan/materials folder and drag the fan_body_mat_0 material to the fan body, and the fan_propeller_mat_0 material — to the blades.打开 archviz/interior/fan/materials 材质目录,fan_body_mat_0 材质指定给风扇主体和 fan_propeller_mat_0 材质指定给扇叶组件。

  3. Now, let's write a component that will rotate its blades. Create a new component, name it Fan and write the following code:现在,我们来编写一个用于旋转风扇叶片的组件。创建一个新组件,命名为 Fan,并编写以下代码:

    Fan.h
    #pragma once
    #include <UnigineComponentSystem.h>
    class Fan :
    	public Unigine::ComponentBase
    {
    public:
    	// 声明组件构造函数/析构函数,并定义关联属性(property)名称
    	// 首次运行后将在项目data目录生成Fan.prop属性文件
    	COMPONENT_DEFINE(Fan, ComponentBase);
    
    	// 组件参数声明及初始化
    	PROP_PARAM(Node, fan_node, nullptr);			// 需要旋转的扇叶节点
    	PROP_PARAM(Float, speed, 720.0f);			// 旋转速度
    
    	// 注册将在世界逻辑相应阶段调用的方法(方法在下面的protected部分中声明)
    	COMPONENT_UPDATE(update);
    
    protected:
    	// 声明将在世界逻辑相应阶段调用的方法
    	void update();
    };
    Fan.cpp
    #include "Fan.h"
    #include <UnigineGame.h>
    // 注册Fan组件
    REGISTER_COMPONENT(Fan);
    
    // 注入必要的命名空间
    using namespace Unigine;
    using namespace Math;
    
    // 每帧调用的组件 update 方法
    void Fan::update()
    {
    	// 如果风扇叶片节点未分配,则不执行任何操作
    	if (!fan_node)
    		return;
    	// 以指定速度旋转节点
    	fan_node->rotate(0, speed * Game::getIFps(), 0);
    }
  4. Let's save our files and then build and run our application by hitting Ctrl + F5 to make the Component System generate a property to be used to assign our component to nodes. Close the application after running it and switch to UnigineEditor.保存文件,然后按Ctrl + F5构建并运行应用程序,使组件系统生成用于将组件分配给节点的属性文件。运行应用程序后将其关闭,然后切换到UnigineEditor。

    Create NodeDummy, name it fan_rotator, and assign our new generated Fan property to it. Customize the Fan component by dragging the fan_table_propeller node into the Fan Node field and setting the rotation speed of the blades.创建NodeDummy节点,命名为fan_rotator,并将我们新生成的Fan属性分配给它。通过将fan_table_propeller节点拖到Fan Node字段并设置叶片的旋转速度来自定义Fan组件。

  5. Let's add fan_rotator to the child nodes of fan_table_lod_0, assign the Toggle component to the fan_table_switch node, and drag the fan_rotator node into the Control Node field.fan_rotator添加为fan_table_lod_0的子节点,为fan_table_switch节点分配Toggle组件,并将fan_rotator节点拖到Control Node字段。
  6. 然后我们应该禁用fan_rotator节点(通过在Parameters(参数)窗口中取消节点名称旁边的复选框),以防止旋转扇叶的组件代码在我们打开开关前执行。

  7. We're going to rotate the fan_table_propeller node, by default it's Mobility is set to Immovable, so we have to switch it to Dynamic.我们将旋转 fan_table_propeller节点,默认情况下它的Mobility设置为Immovable,因此我们需要将其改为Dynamic

  8. Save the world by hitting Ctrl + S. Switch to SDK Browser and launch our application by clicking the Run button on our project's card to see the result.Ctrl + S保存场景。切换到SDK Browser,通过点击项目卡片上的Run按钮启动我们的应用程序以查看结果。

本页面上的信息适用于 UNIGINE 2.20 SDK.

最新更新: 2025-06-09
Build: ()