Skip to content

类型转换

不同的类型之间,不能直接进行操作,此时就需要用到类型转换

gdscript
var integer: int = "100" # 错误,无法将字符串赋值给整数

类型转换的方法

转换类型可以使用如下方法

  • 构造函数(Constructor)(int(), float())可以进行兼容类型间的强制转换

  • type_convert(Variant, Variant.Type),将给定的值转化为目标类型,转换失败时返目标类型的默认值

  • str(),尽可能以最佳方式将一个或多个任何 Variant类型的参数转换为一个 String

  • var_to_str(Variant),将给定值转化为格式化的String

  • str_to_var(String),将var_to_str(Variant)返回的已格式化的string转化为原始Variant

构造函数转换

以基础类型为例,兼容的类型如下表

类型兼容类型构造函数
intStringbool, float, intint(String),int(bool),int(float)int(int)
floatString, bool, int, floatfloat(String), float(bool), float(int), float(float)
boolfloat, int, boolbool(float), bool(int), bool(bool)
StringNodePath, StringName, StringString(NodePath), String(StringName), String(StringName)
StringNameString, StringNameStringName(String), StringName(StringName)
NodePathString, NodePathNodePath(String), NodePath(NodePath)

在使用构造函数转换类型时需要注意的有

  • 将代表整数的字符串转换为int时会遵循如下规则

    • 删除所有非数字字符,除了字符串首位的负号(-)

    • 遇到小数点(.)后停止(int("-1.2.3")将会返回-1

    • 转换失败将得到int默认值(print(int("abc")) # 会输出 0,而不是报错

转换前最好加上检查: print("abc".is_valid_int()) # 会输出 false

  • 将代表十进制数的字符串转化为float时会遵循如下规则

    • 在首个非数字字符处停止(float("12xy3")将会得到12.0)

    • 除非是首次遇到小数点(.)或指数标记(e/E)、正负号(+/-)(float("1e3")结果为1000.0, float("12.3.1")结果为12.3)

    • 转换失败将得到float默认值print(float("abc")) # 会输出 0.0,而不是报错

    转换前最好加上检查: print("abc".is_valid_float()) # 会输出 false

  • 尽量避免StringStringName的频繁转换

gdscript
var integer: int = int("100")
var str: String = "3.14159"
var float_number: float = float(str)

type_convert(Variant, Variant.Type)转换

万能转换方法,将给定的值转换为目标值,失败时转换的结果是目标类型的默认值

第一个参数是需要转换的值

第二个参数是目标类型,是一个Variant.Type枚举常量,也可以直接传入一个整数

虽然转换后的结果是一个Variant,但其数据和类型和请求的目标类型是相同的

gdscript
var a : int = type_convert("Hi!", TYPE_INT) # a的值是0
var b : int = type_convert("123", TYPE_INT) # b的值是123
var c : int = type_convert(123.4, TYPE_INT) # c的值是123
var d : Vector2 = type_convert(5, TYPE_VECTOR2) # d的值是(0.0, 0.0)
var e = type_convert("Hi!", TYPE_NIL) # e的值是<null>
Variant.Type枚举:
枚举常量整数值对应类型
TYPE_NIL0null
TYPE_BOOL1bool
TYPE_INT2int
TYPE_FLOAT3float
TYPE_STRING4String
TYPE_VECTOR25Vector2
TYPE_VECTOR2I6Vector2i
TYPE_RECT27Rect2
TYPE_RECT2I8Rect2i
TYPE_VECTOR39Vector3
TYPE_VECTOR3I10Vector3i
TYPE_TRANSFORM2D11Transform2D
TYPE_VECTOR412Vector4
TYPE_VECTOR4I13Vector4i
TYPE_PLANE14Plane
TYPE_QUATERNION15Quaternion
TYPE_AABB16AABB
TYPE_BASIS17Basis
TYPE_TRANSFORM3D18Transform3D
TYPE_PROJECTION19Projection
TYPE_COLOR20Color
TYPE_STRING_NAME21StringName
TYPE_NODE_PATH22NodePath
TYPE_RID23RID
TYPE_OBJECT24Object及其子类
TYPE_CALLABLE25Callable
TYPE_SIGNAL26Signal
TYPE_DICTIONARY27Dictionary
TYPE_ARRAY28Array
TYPE_PACKED_BYTE_ARRAY29PackedByteArray
TYPE_PACKED_INT32_ARRAY30PackedInt32Array
TYPE_PACKED_INT64_ARRAY31PackedInt64Array
TYPE_PACKED_FLOAT32_ARRAY32PackedFloat32Array
TYPE_PACKED_FLOAT64_ARRAY33PackedFloat64Array
TYPE_PACKED_STRING_ARRAY34PackedStringArray
TYPE_PACKED_VECTOR2_ARRAY35PackedVector2Array
TYPE_PACKED_VECTOR3_ARRAY36PackedVector3Array
TYPE_PACKED_COLOR_ARRAY37PackedColorArray
TYPE_PACKED_VECTOR4_ARRAY38PackedVector4Array
TYPE_MAX39Variant.Type枚举的最大值

str()转换

尽可能以最佳的方式将一个或多个任何类型的值转换为字符串

gdscript
var a = [10, 20, 30]
var b = 3.1415
print(str(a, b)) # 输出"[10, 20, 30]3.1415"
print(str(a)) # 输出"[10, 20, 30]"

var_to_str(Variant)转换

将给定的值转化为格式化的字符串,区别于str()

对对象使用时将得到一个其所有属性都被格式化的字符串

常用于数据的序列化

gdscript
var a = { "a": 1, "b": 2 }
print(var_to_str(a))
print(str(a))

输出:

gdscript
# var_to_str:
{
        "a": 1,
        "b": 2
}

# str:
{ "a": 1, "b": 2 }

不支持转换信号(Signal)和可调用体(Callable),无论他们有什么数据,转换后始终是空值


str_to_var(String)转换

尝试将已格式化的字符串转化为原始的Variant

常用于数据的反序列化

gdscript
var data = '{ "a": 1, "b": 2 }' # data 是一个 String
var dict = str_to_var(data)     # dict 是一个 Dictionary
print(dict["a"])                # 输出 1

自动类型推断

在声明变量并初始化时,可以自动推断类型,这种情况可以省略类型名称

语法如下

  • var 变量名 := 有效初始值

var a: int = 100 等效于 var a := 100

var node: Sprite2D = Sprite2D.new() 等效于 var node := Sprite2D.new()

有效的初始值是指指定的值具有定义的类型:

  • 内置类型(如 int, bool, Vector2等)

  • 引擎的对象类型(如Node, Resource等)

  • 包含脚本资源的常量名(如 MyScript ,前提是声明了 const MyScript=preload("res://my_script.gd")

  • 同一脚本中的內部类,需要注意作用域(比如:在相同作用域内,在 class InnerClass 中声明 class NestedClass 则会得到 InnerClass.NestedClass

  • 通过class_name声明的全局类

  • 自动加载的单例节点

无法对Variant类型进行自动类型推断:

gdscript
var a = 10 # 不设置类型,实际上是Variant
var b := a # 错误,无法推断变量b的类型,因为变量b或变量a没有设置类型

as关键字

强制转换运算符,常用于引用类型间的转换

要转换的值 as 目标类型

对于对象类型,如果值的类型是目标类型或目标类型的子类,进行转换后会得到同一个对象

gdscript
var my_node2D: Node2D
my_node2D = $Sprite2D as Node2D # Sprite2D是Node2D的子类,所以会转换成功

$NodePath是方法get_node("NodePath")的简写

除此之外,get_node("%UniqueNode")的简写是%UniqueNode,以唯一名称获取节点

如果值的类型不是目标类型也不是目标类型的子类,会导致转换失败,虽然不会报错,但会得到null

gdscript
var my_node2D: Node2D
my_node2D = $Button as Node2D # 返回的结果将是`null`,因为Button不是Node2D的子类

也就是说,对于类来说,as只能向上转换(子类→父类),不能向下转换(父类→子类),就像一个家庭,不能凭空产生家谱中没有的家族成员

对于内置类型,如果允许,即支持使用构造函数进行转换,也可以进行强制转换,否则将触发报错,因此推荐将其用于引用类型间的转换

例如不能将NodePathStringName使用as转换为bool,因为其构造函数不存在该转换

gdscript
var my_int: int
my_int = true as int # 得到的结果是1
my_int = Vector2() as int # 错误,两个类型间不兼容,无法转换

对于String类型,即使Stringint, float兼容,也不能对常量值使用as,必须使用String类型的变量,转换的行为也同使用构造函数一样

gdscript
var my_int: int = "123" as int # 错误,无法将字符串转换为整数
var my_str: String = "123"
var my_int: int = my_str as int # 正确语法
var my_float: float = "3.14" as float # 错误,无法将字符串转化为浮点数
var my_str_2: String = "3.14"
var my_float: float = my_str_2 as float # 正确语法

# 注意:这样写虽然不会在编辑器中报错,但是会在运行时报错
var my_str :String= "true"  
var my_bool:bool = my_str as bool # Invalid cast: could not convert value to 'bool'.

在进行场景树交互时,as关键字非常有用,因为get_child, get_node 的结果其值的类型是Node,而不是我们需要的目标类型,它有可能是其他类型的节点,所以这个时候需要使用强制类型转换

gdscript
var my_sprite := $Character as Sprite2D
($AnimPlayer as AnimationPlayer).play("walk")

一些练习

  1. 想一想可以用哪些方法将字符串"123"转化为整数

  2. 总结一下各种转换类型的方法、使用场景以及注意点

  3. 想一想这段代码的等价写法有哪些:var value := str(100)