This page has been translated automatically.
视频教程
界面
要领
高级
实用建议
专业(SIM)
UnigineEditor
界面概述
资源工作流程
版本控制
设置和首选项
项目开发
调整节点参数
Setting Up Materials
设置属性
照明
Sandworm
使用编辑器工具执行特定任务
如何擴展編輯器功能
嵌入式节点类型
Nodes
Objects
Effects
Decals
光源
Geodetics
World Nodes
Sound Objects
Pathfinding Objects
Players
编程
基本原理
搭建开发环境
使用范例
C++
C#
UUSL (Unified UNIGINE Shader Language)
Plugins
File Formats
材质和着色器
Rebuilding the Engine Tools
GUI
VR Development
双精度坐标
应用程序接口
Animations-Related Classes
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
VR-Related Classes
创建内容
内容优化
材质
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Tutorials
注意! 这个版本的文档是过时的,因为它描述了一个较老的SDK版本!请切换到最新SDK版本的文档。
注意! 这个版本的文档描述了一个不再受支持的旧SDK版本!请升级到最新的SDK版本。

Scope. Namespaces

警告
UnigineScript的应用范围仅限于实现与材质相关的逻辑(材质表达式,可编写脚本的材质,画笔材质)。 不要将UnigineScript用作应用程序逻辑的语言,请改用C#/C++,因为这些API是首选的。 无法保证UnigineScript中新引擎功能的可用性(超出其应用范围),因为当前的支持级别仅假设已解决关键问题。

ScopeScope(作用域)#

Scope决定某种在程序中进行使用的标识符在程序中的可访问区域,这种标识符可以是一个变量,一种枚举类型,一种函数,一个类,一个命名空间等。

注意
对于变量,作用域决定了着其可访问性及生命期,而生命期并受当前作用域的限制(具体细节信息请参看下列内容)。

作用域范围的大小取决于声明标识符的地点。例如如果在某个类的顶端位置处声明了一个变量,那么此变量的作用域便是整个类中的所有方法所涉及的范围。但如果在某个方法中声明了一个变量,那么此变量的作用域范围仅限于此方法的作用域范围内。

使用一组花括号({}) 定义一个新的作用域。

例如:

源代码 (UnigineScript)
namespace Foo {
    int a = 10;
}
int a = 5;
log.message("Foo::a is %d, a is %d", Foo::a,a);
输出
Foo::a is 10, a is 5

如果在所有模块的外部使用花括号封装并声明一个标识符,那么此标示符的作用域为全局范围。这就是说声明此标识符后可在程序中的任意位置处访问此标识符。

注意
如果某种函数并未类的成员并在所有模块外部进行声明,那么同样此函数的作用域为全局范围。
例如:
源代码 (UnigineScript)
// foo()方法的作用域为全局范围
int foo() { log.message("Function in the global scope\n"); }

class Foo {
    Foo (){}
    // foo() 方法的作用域仅限Foo类的范围
    int foo(){ log.message("Class member function\n"); }
};

如上所述,变量的生命期并不受当前范围的限制。换句话说即本地变量的生命期与全局变量的生命期相同(除非 另有 注明)。例如:

源代码 (UnigineScript)
int foo() {
    int local_var;
    local_var++;
    log.message("local_var: %d\n",local_var);
}

foo(); // local_var: 1
foo(); // local_var: 2
这种情况下,local_var的变量生命期并不受foo()范围的限制。因此在第二次调用foo()时,先前调用得到的值会增加。用C++的话说就是,其与使用静态修饰符声明的变量相似。

如果要对变量local_var的局部生命期进行仿真,应以如下方式对此变量进行初始化:

源代码 (UnigineScript)
int foo() {
    int local_var = 0;
    local_var++;
    log.message("local_var: %d\n",local_var);
}

foo(); // local_var: 1
foo(); // local_var: 1

Scope Resolution Operator作用域解析运算符#

作用域解析运算符::被用来指定运算符涉及的语境。也可使用此运算符来访问命名空间外的变量,类作用域外的函数或者处理某个标识符的作用域。使用此标识符来表述全局变量及类中的成员。

通过::为函数(变量,类,命名空间等)名增加一个前缀,指定使用全局范围的函数。这样可以确保范围解析将从全局范围开始而不从当前范围开始。例如:

源代码 (UnigineScript)
namespace Test {
    int a;
    void info() { log.message("a from the scope of the 1st namespace is %d\n",a); }
}

int init () {

    namespace Test {
        int a;
        void info() { log.message("a from the scope of the 2nd namespace is %d\n",a); }
    }
	// 访问全局命名空间的成员
    ::Test::a = 10;
    ::Test::info();
	
	// 访问在当前作用域内声明的命名空间成员
    Test::a = 30;
    Test::info();

    return 1;
}
输出结果如下:
输出
a from the scope of the 1st namespace is 10 
a from the scope of the 2nd namespace is 30

注意
UnigineScript函数库中的函数具有全局作用域。因此如果函数名被再次用来在其它域内定义用户函数,::运算符可以确保UnigineScript库中函数为全局解析范围。

假设用户自定义类中某个函数的函数名与UnigineScript库中某个函数名相同。 要在用户自定义函数的作用域范围内调用原始UnigineScript函数,将 :: 运算符作为函数的前缀添加到函数名称前。 例如:

源代码 (UnigineScript)
class Foo {
    Foo() {}

    // 在Foo类解析范围内的用户自定义函数
    void rotate(float angle) {
        // UnigineScript函数用来获取按照所给角度围绕轴旋转的矩阵 
        mat4 rot = ::rotate(vec3(1.0f, 0.0f, 0.0f), angle);
    }
};
如果未指定::运算符,解析器会在控制台中输出如下内容:
源代码
NameSpace::getFunctionID(): can't find "rotate" function with 2 arguments

Namespaces命名空间#

Namespaces可对诸如类,对象及函数名称实体进行分组。全局作用域可被分成子作用域,每个子作用域具有其自己的名称。

命名空间的格式为:

源代码 (UnigineScript)
namespace identifier {
	// 实体
}

定义命名空间的示例:

源代码 (UnigineScript)
namespace Foo {
	int a = 10;
}
int a = 5;
log.message("Foo::a is %d, a is %d", Foo::a,a);

// 输出: Foo::a is 10, a is 5

也可使用using关键字将命名空间的名称引入当前声明区域。

源代码 (UnigineScript)
namespace Foo::Bar {
	int a = 10;
}

void foo() {
	using Foo::Bar;
	log.message("Foo::Bar::a is %d\n",a);
}
foo();

// 输出: Foo::Bar::a is 10
最新更新: 2023-12-19
Build: ()