是否可通过唯一ID访问指定的SceneKit节点?
SceneKit 节点检索与撤销功能实现解答
你打印输出里看到的0x6000039ef300是SCNNode实例的内存地址,并非苹果官方公开的可用于节点检索的ID属性,直接通过该内存地址获取对应节点的操作不可行,官方文档没有相关API支持,且直接访问内存地址存在极高风险:如果节点已经被释放,访问该地址会直接触发野指针崩溃,完全不建议用这种方式处理。
你可以通过以下几种更安全的方案实现需求:
- 自定义可移动方块节点子类
继承SCNNode创建自定义的MovableBlockNode类,在类中新增moveHistory数组属性专门存储该方块的移动历史数据,创建可推动方块时直接使用该子类实例。交互触发时直接判断节点的类归属,就能直接获取对应节点的移动历史数据,无需额外做全局检索。
示例代码:class MovableBlockNode: SCNNode { var moveHistory: [SCNVector3] = [] // 存储每次移动的位置,也可自定义结构体存更完整的移动信息 } - 用全局映射表维护可移动节点
不自定义子类的情况下,可以创建一个全局的[String: SCNNode]字典,每生成一个可推动方块时生成一个唯一标识,存入节点的userInfo属性中,同时将标识和节点的对应关系存入字典,需要检索时直接从字典取值即可。同时可将移动历史也存入userInfo中:// 节点创建时赋值 let blockID = UUID().uuidString blockNode.userInfo["blockID"] = blockID blockNode.userInfo["moveHistory"] = [] globalBlockMap[blockID] = blockNode - 带规则的name属性检索
给所有可推动方块的name添加统一前缀+唯一序号,比如movable_block_001,后续需要筛选所有可推动节点时,调用rootNode.childNodes(passingTest:)方法,筛选name前缀匹配的节点即可。
实现撤销功能时建议你将移动历史存储为位移、旋转等数值类型,不要直接存储节点实例,避免出现循环引用导致节点无法被正常释放。
内容的提问来源于stack exchange,提问作者ViktorEvil
相关产品推荐
相关产品推荐

