ResourceLoader.exists
2026/4/14大约 6 分钟
最后更新日期:2026-04-16
最后同步日期:2026-04-15 | Godot 官方原文 — ResourceLoader.exists
ResourceLoader.exists
定义
ResourceLoader.exists 就像在去快递柜取件之前先看看有没有自己的包裹——你不用真的把包裹拿出来,只是查一下"这个东西存不存在"。如果存在,你再去取;如果不存在,就不用白跑一趟了。
在 Godot 中,exists 的作用是在不实际加载资源的情况下,检查某个路径下是否有可用的资源文件。这是一种"轻量级检查"——它不会把文件读进内存,只是确认文件是否存在以及 Godot 是否能识别这个文件格式。
一句话总结
ResourceLoader.exists 的作用是"安全检查":在加载资源之前先确认文件是否存在,避免因路径错误导致程序崩溃。
函数签名
C#
public static bool Exists(string path, string typeHint = "")GDScript
ResourceLoader.exists(path: String, type_hint: String = "") -> bool参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| path | string / String | 是 | 资源文件的路径,如 "res://scenes/level_01.tscn"。必须以 res:// 或 user:// 开头 |
| typeHint | string / String | 否 | 类型提示,用于进一步检查资源是否为指定类型。例如传 "PackedScene" 可以确认路径指向的不仅是存在的文件,而且是一个场景文件 |
返回值
| 类型 | 说明 |
|---|---|
| bool | 路径对应的资源存在且可被 Godot 识别时返回 true;不存在或格式不支持时返回 false |
代码示例
基础用法
最简单的用法——检查一个文件是否存在:
C#
using Godot;
public partial class ResourceCheck : Node
{
public override void _Ready()
{
// 检查资源是否存在
bool hasIcon = ResourceLoader.Exists("res://icon.svg");
GD.Print("icon.svg 存在: " + hasIcon);
// 运行结果: icon.svg 存在: True
bool hasFake = ResourceLoader.Exists("res://not_real_file.png");
GD.Print("not_real_file.png 存在: " + hasFake);
// 运行结果: not_real_file.png 存在: False
}
}GDScript
extends Node
func _ready() -> void:
# 检查资源是否存在
var has_icon = ResourceLoader.exists("res://icon.svg")
print("icon.svg 存在: %s" % has_icon)
# 运行结果: icon.svg 存在: True
var has_fake = ResourceLoader.exists("res://not_real_file.png")
print("not_real_file.png 存在: %s" % has_fake)
# 运行结果: not_real_file.png 存在: False实际场景
在实际游戏开发中,经常需要根据玩家进度动态加载不同的关卡或资源。使用 exists 先检查文件是否存在,可以避免加载不存在的资源导致报错。下面的例子展示了一个安全的关卡切换系统:
C#
using Godot;
public partial class LevelManager : Node
{
private int _currentLevel = 1;
private Node _currentLevelNode;
public override void _Ready()
{
// 尝试加载第一关
SwitchToLevel(_currentLevel);
}
public void SwitchToLevel(int levelNumber)
{
string levelPath = $"res://scenes/levels/level_{levelNumber:D2}.tscn";
// 先检查关卡文件是否存在
if (!ResourceLoader.Exists(levelPath))
{
GD.Print($"关卡 {levelNumber} 不存在(路径: {levelPath})");
GD.Print("可能是通关了所有关卡!");
return;
}
// 再用 typeHint 确认它是场景文件
if (!ResourceLoader.Exists(levelPath, "PackedScene"))
{
GD.PrintErr($"文件 {levelPath} 存在,但不是场景文件!");
return;
}
// 安全地加载并实例化
var scene = ResourceLoader.Load<PackedScene>(levelPath);
var levelInstance = scene.Instantiate();
// 移除旧关卡
if (_currentLevelNode != null)
{
_currentLevelNode.QueueFree();
}
_currentLevelNode = levelInstance;
AddChild(_currentLevelNode);
_currentLevel = levelNumber;
GD.Print($"成功进入第 {_currentLevel} 关");
// 运行结果: 成功进入第 1 关
}
public void NextLevel()
{
SwitchToLevel(_currentLevel + 1);
}
}GDScript
extends Node
var _current_level: int = 1
var _current_level_node: Node
func _ready() -> void:
# 尝试加载第一关
switch_to_level(_current_level)
func switch_to_level(level_number: int) -> void:
var level_path = "res://scenes/levels/level_%02d.tscn" % level_number
# 先检查关卡文件是否存在
if not ResourceLoader.exists(level_path):
print("关卡 %d 不存在(路径: %s)" % [level_number, level_path])
print("可能是通关了所有关卡!")
return
# 再用 type_hint 确认它是场景文件
if not ResourceLoader.exists(level_path, "PackedScene"):
push_error("文件 %s 存在,但不是场景文件!" % level_path)
return
# 安全地加载并实例化
var scene = ResourceLoader.load(level_path)
var level_instance = scene.instantiate()
# 移除旧关卡
if _current_level_node != null:
_current_level_node.queue_free()
_current_level_node = level_instance
add_child(_current_level_node)
_current_level = level_number
print("成功进入第 %d 关" % _current_level)
# 运行结果: 成功进入第 1 关
func next_level() -> void:
switch_to_level(_current_level + 1)进阶用法
批量验证一组资源路径,构建一个"可用资源清单"——在模组系统或 DLC 系统中很常用:
C#
using Godot;
public partial class ModValidator : Node
{
public override void _Ready()
{
// ===== 示例 1:批量检查资源 =====
string[] candidateLevels = {
"res://mods/christmas/level_snow.tscn",
"res://mods/halloween/level_graveyard.tscn",
"res://mods/default/level_plains.tscn",
"res://mods/default/level_desert.tscn"
};
GD.Print("=== 可用模组关卡 ===");
foreach (string path in candidateLevels)
{
bool exists = ResourceLoader.Exists(path, "PackedScene");
GD.Print($"{path} => {(exists ? "可用" : "不存在")}");
}
// 运行结果:
// === 可用模组关卡 ===
// res://mods/christmas/level_snow.tscn => 不存在
// res://mods/halloween/level_graveyard.tscn => 不存在
// res://mods/default/level_plains.tscn => 可用
// res://mods/default/level_desert.tscn => 可用
// ===== 示例 2:安全加载模式(先检查再加载)=====
var texture = SafeLoadTexture("res://textures/ui/banner.png");
if (texture != null)
{
GD.Print("Banner 加载成功,尺寸: " + texture.GetSize());
// 运行结果: Banner 加载成功,尺寸: (256, 64)
}
// ===== 示例 3:检查配置文件 =====
if (ResourceLoader.Exists("user://save_data.tres"))
{
GD.Print("发现存档文件,准备加载...");
// 运行结果: 发现存档文件,准备加载...
}
else
{
GD.Print("没有存档文件,将使用默认设置");
// 运行结果: 没有存档文件,将使用默认设置
}
}
private Texture2D SafeLoadTexture(string path)
{
if (!ResourceLoader.Exists(path))
{
GD.Print("纹理文件不存在: " + path);
return null;
}
return ResourceLoader.Load<Texture2D>(path);
}
}GDScript
extends Node
func _ready() -> void:
# ===== 示例 1:批量检查资源 =====
var candidate_levels = [
"res://mods/christmas/level_snow.tscn",
"res://mods/halloween/level_graveyard.tscn",
"res://mods/default/level_plains.tscn",
"res://mods/default/level_desert.tscn"
]
print("=== 可用模组关卡 ===")
for path in candidate_levels:
var exists = ResourceLoader.exists(path, "PackedScene")
print("%s => %s" % [path, "可用" if exists else "不存在"])
# 运行结果:
# === 可用模组关卡 ===
# res://mods/christmas/level_snow.tscn => 不存在
# res://mods/halloween/level_graveyard.tscn => 不存在
# res://mods/default/level_plains.tscn => 可用
# res://mods/default/level_desert.tscn => 可用
# ===== 示例 2:安全加载模式(先检查再加载)=====
var texture = safe_load_texture("res://textures/ui/banner.png")
if texture != null:
print("Banner 加载成功,尺寸: %s" % texture.get_size())
# 运行结果: Banner 加载成功,尺寸: (256, 64)
# ===== 示例 3:检查配置文件 =====
if ResourceLoader.exists("user://save_data.tres"):
print("发现存档文件,准备加载...")
# 运行结果: 发现存档文件,准备加载...
else:
print("没有存档文件,将使用默认设置")
# 运行结果: 没有存档文件,将使用默认设置
func safe_load_texture(path: String) -> Texture2D:
if not ResourceLoader.exists(path):
print("纹理文件不存在: %s" % path)
return null
return ResourceLoader.load(path)注意事项
- 不加载资源,只检查存在性:
exists不会把资源读入内存,它只是快速确认文件是否存在且 Godot 能识别。因此即使文件很大,调用exists的开销也非常小。 typeHint是可选的双重保险:如果你只传path参数,exists只检查文件是否存在;如果你同时传了typeHint(如"Texture2D"),它还会额外检查文件是否属于该类型。这在防止加载错误类型的资源时非常有用。- 导出项目中的特殊行为:在导出(Export)后的游戏中,Godot 会把资源打包成
.pck文件。exists同样适用于打包后的资源路径,但在导出时需要确保相关资源被正确包含(检查导出设置中的过滤器)。 - 不适用于检查文件夹:
exists只能检查资源文件,不能用于判断某个目录是否存在。 - C# 差异:C# 中方法名用 PascalCase(
Exists),GDScript 中用 snake_case(exists)。
