核心类型
Godot具有构成其核心的丰富的类和模板集,并且所有内容都基于它们构建.
这份参考将试着按顺序列出它们,使之更容易被理解.
定义
Godot使用标准的C99数据类型,如 uint8_t
, uint32_t
, int64_t
等,现在每个编译器都支持.为这些东西重新造轮子并不有趣,因为它使代码更难阅读.
通常,除非使用大型结构或数组,否则不必在意是否使用给定任务的最有效数据类型.除非必要,否则 int
将用于大多数代码.这样做是因为如今每个设备至少具有32位总线,并且可以在一个周期中执行这样的操作.它也使代码更具可读性.
对于文件或内存大小,使用 size_t
,保证为64位.
对于Unicode字符,使用CharType而不是wchar_t,因为许多体系结构具有4个字节长的wchar_t,其中可能需要2个字节.但是,默认情况下,这不会被强制,CharType会直接映射到wchar_t.
参考:
内存模型
PC是一个很棒的体系结构.计算机通常具有GB级的RAM,TB级的存储空间和千兆赫兹级的CPU,当应用程序需要更多资源时,操作系统将交换不活动的资源.其他架构(如移动设备或游戏主机)在这些方面通常有很多限制.
最常见的内存模型是堆,应用程序会从中请求一块内存区域,底层操作系统会试着从某处找到一块适合这样的内存并返回它.这通常效果最好,并且很灵活,但是随着时间的流逝和滥用,这可能会导致分段.
分段缓慢地产生对于大多数常见分配而言太小的孔洞,从而浪费了内存.关于堆和分段的文献有很多,因此在此不再赘述.现代操作系统使用分页内存,这有助于减轻但不能解决分段问题.
然而,许多的研究和测试显示出,在给出足够内存的情况下,如果最大分配大小所占堆最大大小的比例,低于一个给定比例阈值,即未曾使用的内存比例,分段这件事就不会随着时间的推移成为问题.换句话说,留出10-20%的可用内存空间,再执行小额内存分配,您也没事.
Godot确保所有的可动态分配的对象都很小(最多不到几kb).但是如果出现很大的分配(像图像、网格几何数据或大数组),会怎样呢?在这种情况下,Godot可以选择使用动态内存池.内存会被锁定以进行访问操作;如果内存不足,则内存池会根据需要进行重新排列和压缩.根据游戏的需要,程序员可以配置动态内存池的大小.
内存分配
Godot有许多工具可用于跟踪游戏中的内存使用情况,尤其是在调试期间.因此,不应使用常规的C和C++库调用.相反,Godot提供了一些其它的供您使用.
Godot提供了一些宏可以用来处理C风格的内存分配:
memalloc()
memrealloc()
memfree()
这些等效于标准C库中通常的malloc、realloc、free.
这些宏可以用来处理C++风格的内存分配:
memnew( Class / Class(args) )
memdelete( instance )
memnew_arr( Class , amount )
memdelete_arr( pointer to array )
这些等效于new、delete、new[]和delete[].
memnew/memdelete也使用一点C++的小技巧,在对象创建之后和删除之前,通知对象.
对于动态内存,提供了PoolVector<>模板.PoolVector是一个标准的Vector类,与C++标准库中的vector非常相似.要创建PoolVector缓冲区,请使用以下命令:
PoolVector<int> data;
可以使用[]运算符访问PoolVector,并且存在一些帮助:
PoolVector<int>::Read r = data.read()
int someint = r[4]
PoolVector<int>::Write w = data.write()
w[4] = 22;
这些操作允许从PoolVectors快速读/写并保持锁定直到它们超出作用域.但是,PoolVectors应该用于小型动态内存操作,因为read()和write()对于大量访问来说太慢了.
参考:
容器
Godot 还提供了一系列通用的容器:
向量
List
设置
Map
它们很简单,旨在尽可能小,因为C++中的模板经常被内联,并且在调试符号和代码中使二进制大小更加大.可以使用指针迭代List、Set和Map,如下所示:
for(List<int>::Element *E=somelist.front();E;E=E->next()) {
print_line(E->get()); // print the element
}
Vector<>类还具有一些不错的功能:
它会在写入时进行复制,因此只要不对其进行修改,制作拷贝就很容易.
通过在引用计数器上使用原子操作,来支持多线程.
参考:
字符串
Godot 还提供了一个字符串类 String.Godot还提供了String类. 此类具有大量功能,在所有函数(如大小写操作)和utf8解析/提取中均提供全面的Unicode支持,以及提供用于转换和可视化的帮助函数.
参考:
字符串名称(StringName)
字符串名称和字符串类似,不同的是它们是唯一的.从字符串创建StringName会为所有相等的字符串产生唯一的内部指针.StringNames对于将字符串用作标识符非常有用,因为比较它们基本上是在比较指针.
创建一个字符串名称(尤其是一个新的) 是慢的, 但比较它们是快的.
参考:
数学类型
在core/math目录中,有几种线性代数常用的类型.
参考:
节点路径
这是一种特殊的数据类型,用于在场景树中存储路径并快速引用它们.
参考:
RID
RID是资源ID.服务使用这些来引用存储在其中的数据.RID是不透明的,这意味着它们引用的数据不能直接访问.RID是唯一的,甚至对于不同类型的引用数据也是如此.