is_instance_valid
最后同步日期:2026-04-15 | Godot 官方原文 — is_instance_valid
is_instance_valid
定义
is_instance_valid() 用于检查给定的对象引用是否仍然有效(没有被销毁)。
在 Godot 中,当你调用 queue_free() 或 free() 销毁一个节点后,任何持有该节点引用的变量都不会自动变成 null——它们仍然指向那块内存,但对象已经不存在了。如果你试图使用这些"失效"的引用,程序就会崩溃。
is_instance_valid() 就是帮你检查"这个引用还有没有效"的工具。就像检查一张优惠券是否过期:优惠券还在你手里(引用还在),但可能已经过期了(对象被销毁了)。
函数签名
// C# 中使用 GodotObject.IsInstanceValid
bool valid = GodotObject.IsInstanceValid(GodotObject instance);func is_instance_valid(instance: Variant) -> bool参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
instance | Variant | 是 | 要检查的对象引用。如果传入 null,返回 false |
返回值
bool —— 返回 true 表示对象仍然有效,可以安全使用;返回 false 表示对象已被销毁或引用为 null。
代码示例
基础用法:检查对象是否还有效
using Godot;
public partial class IsInstanceValidExample : Node
{
private Node _target;
public override void _Ready()
{
_target = new Node();
_target.Name = "Target";
AddChild(_target);
GD.Print($"对象有效? {GodotObject.IsInstanceValid(_target)}");
// 运行结果: 对象有效? True
_target.QueueFree();
// 注意:queue_free 是延迟销毁,当前帧内仍然有效
GD.Print($"queue_free 后(同帧): {GodotObject.IsInstanceValid(_target)}");
// 运行结果: queue_free 后(同帧): True
}
public override void _Process(double delta)
{
// 下一帧检查
if (_target != null)
{
GD.Print($"下一帧检查: {GodotObject.IsInstanceValid(_target)}");
// 运行结果: 下一帧检查: False
}
}
}extends Node
var _target: Node
func _ready():
_target = Node.new()
_target.name = "Target"
add_child(_target)
print("对象有效? ", is_instance_valid(_target))
# 运行结果: 对象有效? True
_target.queue_free()
# 注意:queue_free 是延迟销毁,当前帧内仍然有效
print("queue_free 后(同帧): ", is_instance_valid(_target))
# 运行结果: queue_free 后(同帧): True实际场景:安全的引用持有
using Godot;
public partial class TargetTracker : Node
{
private Node _currentTarget;
public void SetTarget(Node target)
{
_currentTarget = target;
GD.Print($"锁定目标: {target?.Name}");
}
public override void _Process(double delta)
{
if (_currentTarget == null || !GodotObject.IsInstanceValid(_currentTarget))
{
_currentTarget = null;
return;
}
// 安全地使用目标
GD.Print($"追踪目标: {_currentTarget.Name}");
}
}extends Node
var _current_target: Node
func set_target(target: Node) -> void:
_current_target = target
print("锁定目标: ", target.name)
func _process(_delta: float) -> void:
if not is_instance_valid(_current_target):
_current_target = null
return
# 安全地使用目标
print("追踪目标: ", _current_target.name)进阶用法:管理观察者列表
using Godot;
using System.Collections.Generic;
public partial class ObserverManager : Node
{
private readonly List<Node> _observers = new();
public void AddObserver(Node observer)
{
_observers.Add(observer);
}
public void NotifyAll(string message)
{
// 先清理失效的观察者
_observers.RemoveAll(obs => !GodotObject.IsInstanceValid(obs));
foreach (var observer in _observers)
{
GD.Print($"通知 {observer.Name}: {message}");
}
}
public override void _Process(double delta)
{
// 定期清理失效引用
int removed = _observers.RemoveAll(obs => !GodotObject.IsInstanceValid(obs));
if (removed > 0)
{
GD.Print($"清理了 {removed} 个失效观察者");
}
}
}extends Node
# 内部变量:观察者列表
var _observers: Array = []
func add_observer(observer: Node) -> void:
_observers.append(observer)
func notify_all(message: String) -> void:
# 先清理失效的观察者
_observers = _observers.filter(func(obs): return is_instance_valid(obs))
for observer in _observers:
print("通知 %s: %s" % [observer.name, message])
func _process(_delta: float) -> void:
# 定期清理失效引用
var old_size = _observers.size()
_observers = _observers.filter(func(obs): return is_instance_valid(obs))
var removed = old_size - _observers.size()
if removed > 0:
print("清理了 %d 个失效观察者" % removed)注意事项
与
is_instance_id_valid()的区别:is_instance_valid()接收的是对象引用,is_instance_id_valid()接收的是实例 ID(一个数字)。如果你手里有的是对象引用,用is_instance_valid();如果是实例 ID,用is_instance_id_valid()。queue_free()的延迟:queue_free()不是立即销毁对象,而是在当前帧结束时才销毁。所以在同一帧内is_instance_valid()仍然返回true。如果需要立即销毁,可以用free(),但要格外小心。null检查不能代替此函数:在 GDScript 中,被销毁的对象引用不会自动变成null。你必须使用is_instance_valid()来检查,单纯判断if obj:或if obj != null:是不够的。C# 中使用
GodotObject.IsInstanceValid():C# 中对应的函数是GodotObject.IsInstanceValid(GodotObject instance),行为一致。
