@static_unload
2026/4/14大约 4 分钟
最后更新日期:2026-04-16
最后同步日期:2026-04-15 | Godot 官方原文 — @static_unload
@static_unload
定义
@static_unload 是 GDScript 中的一个注解(annotation),用来告诉 Godot 在不再需要这个脚本时自动卸载它的静态变量和静态初始化代码,释放内存。
在 GDScript 中,当你使用 class_name 注册全局类时,Godot 会在项目运行期间一直保留这个脚本在内存中,即使没有任何地方使用它。对于大多数脚本来说这没问题,但如果你的项目有很多全局类,或者某些全局类初始化时占用了大量资源(比如加载了大文件),就会造成不必要的内存浪费。
@static_unload 就是解决这个问题的:它让 Godot 在脚本不再被引用时,能够回收它占用的内存。
简单说,就像离开房间时随手关灯——不用的时候就释放,省资源。
C# 中没有直接等价的特性,因为 C# 的垃圾回收机制(GC)会自动处理内存释放。
语法
C#
// C# 中没有直接等价的 @static_unload
// C# 的垃圾回收机制(GC)会自动处理内存释放
// 无需手动干预
// 如果需要类似的清理逻辑,可以实现 IDisposable 接口
public partial class GameManager : Node
{
public override void _ExitTree()
{
// 清理资源
}
}GDScript
# 在脚本顶部添加 @static_unload
@static_unload
class_name GameManager
extends Node
# 脚本不再被引用时,静态变量会被自动清理
static var _instance_count: int = 0参数说明
@static_unload 不需要任何参数——它直接写在脚本的最顶部即可。
| 说明项 | 详情 |
|---|---|
| 放置位置 | 脚本的最顶部 |
| 适用场景 | 使用了 class_name 且包含 static 变量的脚本 |
| 效果 | 脚本不再被引用时,自动卸载静态数据 |
返回值
@static_unload 是一个注解,没有返回值。它的作用是改变脚本的内存管理行为。
代码示例
C#
using Godot;
// C# 中没有 @static_unload 的概念
// GC 会自动处理。这里展示类似的清理模式
// ===== 基础用法:C# 中的资源清理 =====
public partial class GameManager : Node
{
private static int _instanceCount = 0;
private System.Collections.Generic.List<Node> _managedNodes = new();
public override void _Ready()
{
_instanceCount++;
GD.Print($"GameManager 实例数: {_instanceCount}");
}
// 运行结果: GameManager 实例数: 1
public override void _ExitTree()
{
_instanceCount--;
_managedNodes.Clear();
GD.Print($"GameManager 已清理,剩余实例: {_instanceCount}");
}
// 运行结果: GameManager 已清理,剩余实例: 0
// ===== 实际场景:单例模式与清理 =====
public partial class AudioManager : Node
{
private static AudioManager _instance;
public static AudioManager Instance => _instance;
private Godot.Collections.Array<AudioStream> _loadedSounds = new();
public override void _Ready()
{
_instance = this;
GD.Print("AudioManager 初始化");
}
public override void _ExitTree()
{
_loadedSounds.Clear();
_instance = null;
GD.Print("AudioManager 已清理");
}
}
// 运行结果: AudioManager 初始化
// 运行结果: AudioManager 已清理
// ===== 进阶用法:使用 IDisposable =====
public partial class ResourceLoader : Node, System.IDisposable
{
private bool _disposed = false;
public void LoadResources()
{
GD.Print("资源已加载");
}
public void Dispose()
{
if (!_disposed)
{
GD.Print("资源已释放");
_disposed = true;
}
}
}
// 运行结果: 资源已加载
// 运行结果: 资源已释放
}GDScript
# ===== 基础用法:自动卸载静态数据 =====
@static_unload
class_name GameManager
extends Node
static var _instance_count: int = 0
func _ready():
GameManager._instance_count += 1
print("GameManager 实例数: %d" % GameManager._instance_count)
# 运行结果: GameManager 实例数: 1
# ===== 实际场景:带静态缓存的全局类 =====
@static_unload
class_name TextureCache
extends Node
static var _cache: Dictionary = {}
static func get_texture(path: String) -> Texture2D:
if path not in _cache:
_cache[path] = load(path)
print("缓存新纹理: %s" % path)
return _cache[path]
static func clear_cache():
var count := _cache.size()
_cache.clear()
print("已清空 %d 个缓存纹理" % count)
func _ready():
var tex := TextureCache.get_texture("res://icon.svg")
print("纹理尺寸: %s" % tex.get_size())
# 运行结果: 缓存新纹理: res://icon.svg
# 运行结果: 纹理尺寸: (128, 128)
# ===== 进阶用法:多全局类场景 =====
# 当项目有多个全局类时,@static_unload 可以防止内存泄漏
@static_unload
class_name ConfigManager
extends RefCounted
static var _settings: Dictionary = {}
static var _loaded: bool = false
static func load_settings():
if _loaded:
return
_settings = {
"volume": 0.8,
"language": "zh_CN",
"fullscreen": false
}
_loaded = true
print("配置已加载: %s" % str(_settings))
static func get_setting(key: String, default: Variant = null) -> Variant:
if not _loaded:
load_settings()
return _settings.get(key, default)
func _init():
ConfigManager.load_settings()
print("音量: %.1f" % ConfigManager.get_setting("volume", 1.0))
# 运行结果: 配置已加载: { "volume": 0.8, "language": "zh_CN", "fullscreen": false }
# 运行结果: 音量: 0.8注意事项
@static_unload只对使用了class_name的 GDScript 脚本有效。如果没有class_name,脚本本来就不会被全局持有,不需要这个注解。@static_unloadC# 中没有等价物。C# 依赖 .NET 的垃圾回收机制自动管理内存。- 使用
@static_unload后,当脚本不再被任何地方引用时,它的静态变量会被清空。如果你的静态变量中存储了需要持久保留的数据,请谨慎使用。 - 这个注解主要用于优化大型项目的内存占用,对于小型项目通常不需要。
- 如果你的脚本包含重要的静态常量或配置,不建议使用
@static_unload,因为这些数据可能在脚本卸载后丢失。 @static_unload应该放在脚本的最顶部,在class_name和extends之前。
