类型转换
不同的类型之间,不能直接进行操作,此时就需要用到类型转换
var integer: int = "100" # 错误,无法将字符串赋值给整数类型转换的方法
转换类型可以使用如下方法
构造函数(Constructor)(
int(),float())可以进行兼容类型间的强制转换type_convert(Variant, Variant.Type),将给定的值转化为目标类型,转换失败时返目标类型的默认值str(),尽可能以最佳方式将一个或多个任何Variant类型的参数转换为一个String。var_to_str(Variant),将给定值转化为格式化的Stringstr_to_var(String),将var_to_str(Variant)返回的已格式化的string转化为原始Variant
构造函数转换
以基础类型为例,兼容的类型如下表
| 类型 | 兼容类型 | 构造函数 |
|---|---|---|
int | String,bool, float, int | int(String),int(bool),int(float),int(int) |
float | String, bool, int, float | float(String), float(bool), float(int), float(float) |
bool | float, int, bool | bool(float), bool(int), bool(bool) |
String | NodePath, StringName, String | String(NodePath), String(StringName), String(StringName) |
StringName | String, StringName | StringName(String), StringName(StringName) |
NodePath | String, NodePath | NodePath(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尽量避免
String到StringName的频繁转换
var integer: int = int("100")
var str: String = "3.14159"
var float_number: float = float(str)type_convert(Variant, Variant.Type)转换
万能转换方法,将给定的值转换为目标值,失败时转换的结果是目标类型的默认值
第一个参数是需要转换的值
第二个参数是目标类型,是一个Variant.Type枚举常量,也可以直接传入一个整数
虽然转换后的结果是一个Variant,但其数据和类型和请求的目标类型是相同的
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_NIL | 0 | null |
TYPE_BOOL | 1 | bool |
TYPE_INT | 2 | int |
TYPE_FLOAT | 3 | float |
TYPE_STRING | 4 | String |
TYPE_VECTOR2 | 5 | Vector2 |
TYPE_VECTOR2I | 6 | Vector2i |
TYPE_RECT2 | 7 | Rect2 |
TYPE_RECT2I | 8 | Rect2i |
TYPE_VECTOR3 | 9 | Vector3 |
TYPE_VECTOR3I | 10 | Vector3i |
TYPE_TRANSFORM2D | 11 | Transform2D |
TYPE_VECTOR4 | 12 | Vector4 |
TYPE_VECTOR4I | 13 | Vector4i |
TYPE_PLANE | 14 | Plane |
TYPE_QUATERNION | 15 | Quaternion |
TYPE_AABB | 16 | AABB |
TYPE_BASIS | 17 | Basis |
TYPE_TRANSFORM3D | 18 | Transform3D |
TYPE_PROJECTION | 19 | Projection |
TYPE_COLOR | 20 | Color |
TYPE_STRING_NAME | 21 | StringName |
TYPE_NODE_PATH | 22 | NodePath |
TYPE_RID | 23 | RID |
TYPE_OBJECT | 24 | Object及其子类 |
TYPE_CALLABLE | 25 | Callable |
TYPE_SIGNAL | 26 | Signal |
TYPE_DICTIONARY | 27 | Dictionary |
TYPE_ARRAY | 28 | Array |
TYPE_PACKED_BYTE_ARRAY | 29 | PackedByteArray |
TYPE_PACKED_INT32_ARRAY | 30 | PackedInt32Array |
TYPE_PACKED_INT64_ARRAY | 31 | PackedInt64Array |
TYPE_PACKED_FLOAT32_ARRAY | 32 | PackedFloat32Array |
TYPE_PACKED_FLOAT64_ARRAY | 33 | PackedFloat64Array |
TYPE_PACKED_STRING_ARRAY | 34 | PackedStringArray |
TYPE_PACKED_VECTOR2_ARRAY | 35 | PackedVector2Array |
TYPE_PACKED_VECTOR3_ARRAY | 36 | PackedVector3Array |
TYPE_PACKED_COLOR_ARRAY | 37 | PackedColorArray |
TYPE_PACKED_VECTOR4_ARRAY | 38 | PackedVector4Array |
TYPE_MAX | 39 | Variant.Type枚举的最大值 |
str()转换
尽可能以最佳的方式将一个或多个任何类型的值转换为字符串
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()
对对象使用时将得到一个其所有属性都被格式化的字符串
常用于数据的序列化
var a = { "a": 1, "b": 2 }
print(var_to_str(a))
print(str(a))输出:
# var_to_str:
{
"a": 1,
"b": 2
}
# str:
{ "a": 1, "b": 2 }不支持转换信号(Signal)和可调用体(Callable),无论他们有什么数据,转换后始终是空值
str_to_var(String)转换
尝试将已格式化的字符串转化为原始的Variant
常用于数据的反序列化
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类型进行自动类型推断:
var a = 10 # 不设置类型,实际上是Variant
var b := a # 错误,无法推断变量b的类型,因为变量b或变量a没有设置类型as关键字
强制转换运算符,常用于引用类型间的转换
要转换的值 as 目标类型
对于对象类型,如果值的类型是目标类型或目标类型的子类,进行转换后会得到同一个对象
var my_node2D: Node2D
my_node2D = $Sprite2D as Node2D # Sprite2D是Node2D的子类,所以会转换成功
$NodePath是方法get_node("NodePath")的简写除此之外,
get_node("%UniqueNode")的简写是%UniqueNode,以唯一名称获取节点
如果值的类型不是目标类型也不是目标类型的子类,会导致转换失败,虽然不会报错,但会得到null值
var my_node2D: Node2D
my_node2D = $Button as Node2D # 返回的结果将是`null`,因为Button不是Node2D的子类也就是说,对于类来说,as只能向上转换(子类→父类),不能向下转换(父类→子类),就像一个家庭,不能凭空产生家谱中没有的家族成员
对于内置类型,如果允许,即支持使用构造函数进行转换,也可以进行强制转换,否则将触发报错,因此推荐将其用于引用类型间的转换
例如不能将NodePath或StringName使用as转换为bool,因为其构造函数不存在该转换
var my_int: int
my_int = true as int # 得到的结果是1
my_int = Vector2() as int # 错误,两个类型间不兼容,无法转换对于String类型,即使String和int, float兼容,也不能对常量值使用as,必须使用String类型的变量,转换的行为也同使用构造函数一样
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,而不是我们需要的目标类型,它有可能是其他类型的节点,所以这个时候需要使用强制类型转换
var my_sprite := $Character as Sprite2D
($AnimPlayer as AnimationPlayer).play("walk")一些练习
想一想可以用哪些方法将字符串
"123"转化为整数总结一下各种转换类型的方法、使用场景以及注意点
想一想这段代码的等价写法有哪些:
var value := str(100)