weakref
2026/4/14大约 4 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — weakref
weakref
定义
weakref() 用于创建一个弱引用(Weak Reference)。普通引用和弱引用的区别在于:
- 普通引用(强引用):你拿着对象的引用,Godot 就不会销毁这个对象,即使其他地方都不需要它了
- 弱引用:你"轻轻触碰"对象,不会阻止 Godot 销毁它。如果对象被销毁了,弱引用会自动变成
null
打个比方:强引用就像你用手紧紧抓住一个气球——只要你抓着,气球就不会飞走。弱引用就像你用一根很细的线连着气球——线不会阻止气球飞走,但你可以在气球还在的时候顺着线找到它。
弱引用主要用于"缓存"和"观察者"场景——你想要引用一个对象,但不想阻止它被正常销毁。
函数签名
C#
// C# 中使用 WeakReference
var weakRef = new System.WeakReference(object);
// 或使用 Godot 的 WeakRef
var weakRef = new Godot.WeakRef();
weakRef.Ref = obj;GDScript
func weakref(obj: Object) -> WeakRef参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
obj | Object | 是 | 要创建弱引用的对象。只能对继承自 Object 的类型使用,不支持基本类型(如 int、float、String) |
返回值
WeakRef —— 一个弱引用对象。你可以通过它的 get_ref() 方法获取原始对象。如果原始对象已被销毁,get_ref() 返回 null。
代码示例
基础用法:创建和使用弱引用
C#
using Godot;
public partial class WeakrefExample : Node
{
public override void _Ready()
{
var target = new Node();
target.Name = "Target";
AddChild(target);
// 创建弱引用
var weakRef = new Godot.WeakRef();
weakRef.Ref = target;
// 通过弱引用获取对象
var retrieved = weakRef.GetRef() as Node;
GD.Print($"弱引用有效? {retrieved != null}"); // True
GD.Print($"对象名: {retrieved?.Name}");
// 运行结果: 对象名: Target
}
}GDScript
extends Node
func _ready():
var target = Node.new()
target.name = "Target"
add_child(target)
# 创建弱引用
var weak_ref = weakref(target)
# 通过弱引用获取对象
var retrieved = weak_ref.get_ref()
print("弱引用有效? ", retrieved != null) # True
print("对象名: ", retrieved.name if retrieved else "已销毁")
# 运行结果: 对象名: Target实际场景:观察者模式中的安全引用
C#
using Godot;
using System.Collections.Generic;
public partial class EventSystem : Node
{
private readonly List<Godot.WeakRef> _listeners = new();
// 注册监听器(使用弱引用,不阻止监听器被销毁)
public void RegisterListener(Node listener)
{
var weakRef = new Godot.WeakRef();
weakRef.Ref = listener;
_listeners.Add(weakRef);
GD.Print($"注册监听器: {listener.Name}");
}
// 通知所有仍然有效的监听器
public void Notify(string eventName)
{
var validListeners = new List<Node>();
foreach (var weakRef in _listeners)
{
var obj = weakRef.GetRef() as Node;
if (obj != null)
{
validListeners.Add(obj);
}
}
GD.Print($"事件 '{eventName}' 通知了 {validListeners.Count} 个监听器");
}
// 清理已失效的弱引用
public void Cleanup()
{
_listeners.RemoveAll(wr => wr.GetRef() == null);
GD.Print($"清理后剩余监听器: {_listeners.Count}");
}
}GDScript
extends Node
# 内部变量:监听器列表(存储弱引用)
var _listeners: Array = []
# 注册监听器(使用弱引用,不阻止监听器被销毁)
func register_listener(listener: Node) -> void:
_listeners.append(weakref(listener))
print("注册监听器: ", listener.name)
# 通知所有仍然有效的监听器
func notify(event_name: String) -> void:
var count = 0
for weak_ref in _listeners:
var obj = weak_ref.get_ref()
if obj:
count += 1
print("事件 '%s' 通知了 %d 个监听器" % [event_name, count])
# 清理已失效的弱引用
func cleanup() -> void:
_listeners = _listeners.filter(func(wr): return wr.get_ref() != null)
print("清理后剩余监听器: ", _listeners.size())进阶用法:资源缓存系统
C#
using Godot;
using System.Collections.Generic;
public partial class ResourceCache : Node
{
private readonly Dictionary<string, Godot.WeakRef> _cache = new();
// 获取或加载资源(使用弱引用缓存)
public T GetOrLoad<T>(string path) where T : class
{
if (_cache.TryGetValue(path, out var weakRef))
{
var cached = weakRef.GetRef();
if (cached != null)
{
GD.Print($"缓存命中: {path}");
return cached as T;
}
else
{
_cache.Remove(path);
}
}
// 缓存未命中,加载资源
var resource = GD.Load<Resource>(path);
if (resource != null)
{
var newWeakRef = new Godot.WeakRef();
newWeakRef.Ref = resource;
_cache[path] = newWeakRef;
GD.Print($"加载并缓存: {path}");
}
return resource as T;
}
}GDScript
extends Node
# 内部变量:资源缓存(存储弱引用)
var _cache: Dictionary = {}
# 获取或加载资源(使用弱引用缓存)
func get_or_load(path: String) -> Resource:
# 检查缓存
if _cache.has(path):
var weak_ref = _cache[path]
var cached = weak_ref.get_ref()
if cached:
print("缓存命中: ", path)
return cached
else:
_cache.erase(path)
# 缓存未命中,加载资源
var resource = load(path)
if resource:
_cache[path] = weakref(resource)
print("加载并缓存: ", path)
return resource注意事项
只支持 Object 类型:
weakref()只能对继承自Object的类型(如Node、Resource、RefCounted)使用。不能对基本类型(int、float、String、Array、Dictionary等)使用弱引用。与强引用的内存管理区别:强引用会阻止垃圾回收,弱引用不会。如果你希望某个对象在被其他地方都不再使用时能被正常释放,就用弱引用来持有它。
使用前检查有效性:通过弱引用获取对象后(调用
get_ref()),务必检查返回值是否为null。如果是null,说明原始对象已经被销毁了。C# 中使用
Godot.WeakRef:C# 中可以创建Godot.WeakRef对象并设置Ref属性来创建弱引用,也可以使用 .NET 的System.WeakReference。
