instance_from_id
2026/4/14大约 4 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — instance_from_id
instance_from_id
定义
instance_from_id() 用于根据实例 ID 找回对应的对象。每个 Godot 对象在创建时都会获得一个唯一的数字 ID,这个函数让你可以用这个 ID 查找并拿回原始对象。
打个比方:你在快递站寄存了一个包裹,工作人员给你一张取件单(实例 ID)。过几天你拿着取件单回来,instance_from_id() 就是工作人员根据取件单帮你找到对应包裹的过程。
这个函数通常和 get_instance_id()(获取取件单)配合使用:先用 get_instance_id() 记录对象的 ID,之后用 instance_from_id() 根据 ID 找回对象。
函数签名
C#
// C# 中使用 GodotObject.InstanceFromId
GodotObject obj = GodotObject.InstanceFromId(ulong id);GDScript
func instance_from_id(instance_id: int) -> Variant参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
instance_id | int(GDScript)/ ulong(C#) | 是 | 目标对象的实例 ID,通常通过 obj.get_instance_id() 获取 |
返回值
Variant —— 对应实例 ID 的对象。如果该 ID 对应的对象已经被销毁或 ID 无效,返回 null。
代码示例
基础用法:通过 ID 找回对象
C#
using Godot;
public partial class InstanceFromIdExample : Node
{
public override void _Ready()
{
// 创建一个节点
var myNode = new Node();
myNode.Name = "MyNode";
AddChild(myNode);
// 记录它的实例 ID
ulong savedId = myNode.GetInstanceId();
GD.Print($"节点的实例 ID: {savedId}");
// 通过 ID 找回节点
var found = GodotObject.InstanceFromId(savedId) as Node;
if (found != null)
{
GD.Print($"找回的节点名: {found.Name}");
// 运行结果: 找回的节点名: MyNode
}
}
}GDScript
extends Node
func _ready():
# 创建一个节点
var my_node = Node.new()
my_node.name = "MyNode"
add_child(my_node)
# 记录它的实例 ID
var saved_id = my_node.get_instance_id()
print("节点的实例 ID: ", saved_id)
# 通过 ID 找回节点
var found = instance_from_id(saved_id)
if found:
print("找回的节点名: ", found.name)
# 运行结果: 找回的节点名: MyNode实际场景:信号传递对象引用
C#
using Godot;
public partial class EventBus : Node
{
// 通过信号传递实例 ID(而不是直接传对象引用)
// 这样可以避免引用管理的问题
[Signal]
public delegate void ObjectCreatedEventHandler(ulong instanceId);
public void EmitObjectCreated(Node obj)
{
EmitSignal(SignalName.ObjectCreated, obj.GetInstanceId());
}
public void OnObjectCreated(ulong instanceId)
{
var obj = GodotObject.InstanceFromId(instanceId) as Node;
if (obj != null)
{
GD.Print($"收到通知,新对象: {obj.Name}");
}
else
{
GD.PrintErr("对象已不存在");
}
}
}GDScript
extends Node
# 通过信号传递实例 ID(而不是直接传对象引用)
signal object_created(instance_id: int)
func emit_object_created(obj: Node) -> void:
object_created.emit(obj.get_instance_id())
func _on_object_created(instance_id: int) -> void:
var obj = instance_from_id(instance_id)
if obj:
print("收到通知,新对象: ", obj.name)
else:
push_error("对象已不存在")进阶用法:对象缓存系统
C#
using Godot;
using System.Collections.Generic;
public partial class ObjectCache : Node
{
private readonly Dictionary<string, ulong> _cache = new();
// 注册对象到缓存
public void Register(string key, GodotObject obj)
{
_cache[key] = obj.GetInstanceId();
GD.Print($"已缓存: {key} -> ID:{obj.GetInstanceId()}");
}
// 从缓存获取对象
public GodotObject Get(string key)
{
if (!_cache.TryGetValue(key, out ulong id))
{
GD.PrintErr($"缓存中不存在: {key}");
return null;
}
var obj = GodotObject.InstanceFromId(id);
if (obj == null)
{
GD.PrintErr($"对象已被销毁: {key}");
_cache.Remove(key);
return null;
}
return obj;
}
// 清理已失效的缓存
public void Cleanup()
{
var keysToRemove = new List<string>();
foreach (var pair in _cache)
{
if (GodotObject.InstanceFromId(pair.Value) == null)
{
keysToRemove.Add(pair.Key);
}
}
foreach (var key in keysToRemove)
{
_cache.Remove(key);
}
GD.Print($"清理完毕,剩余缓存: {_cache.Count}");
}
}GDScript
extends Node
# 内部变量:缓存字典(key -> 实例 ID)
var _cache: Dictionary = {}
# 注册对象到缓存
func register(key: String, obj: Object) -> void:
_cache[key] = obj.get_instance_id()
print("已缓存: %s -> ID:%d" % [key, obj.get_instance_id()])
# 从缓存获取对象
func get_cached(key: String) -> Variant:
if not _cache.has(key):
push_error("缓存中不存在: " + key)
return null
var id = _cache[key]
var obj = instance_from_id(id)
if obj == null:
push_error("对象已被销毁: " + key)
_cache.erase(key)
return null
return obj
# 清理已失效的缓存
func cleanup() -> void:
var keys_to_remove = []
for key in _cache:
if instance_from_id(_cache[key]) == null:
keys_to_remove.append(key)
for key in keys_to_remove:
_cache.erase(key)
print("清理完毕,剩余缓存: ", _cache.size())注意事项
对象必须仍然存在:如果对象已经被销毁(通过
free()或queue_free()),instance_from_id()会返回null。在使用返回值之前,务必进行空值检查。先检查再获取:推荐先用
is_instance_id_valid()检查 ID 是否有效,再用instance_from_id()获取对象。或者直接获取并检查返回值是否为null。ID 不会重复分配:在同一运行会话中,即使对象被销毁了,它的实例 ID 也不会被分配给新对象。所以你不用担心拿到一个 ID 后发现它指向了另一个完全不同的对象。
C# 中使用
GodotObject.InstanceFromId():C# 中返回的是GodotObject类型,通常需要用as关键字转换为具体的子类型(如as Node)。
