You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SKShapeNode子类draw方法访问self.scene为nil问题求解

问题成因
  • SKNode(包括你子类化的SKShapeNode)的scene属性,只有当节点已经被正式加入到场景的节点树中时才会被赋值,未被添加到场景的节点访问scene属性必然返回nil。
  • 你的代码执行顺序逻辑存在问题:在addOuterMovingBlocks方法中,你先执行了shape.setup(number: 1),这个方法内部调用draw(_:)时会访问scene属性,而此时你还没有执行addChild(shape)把节点挂载到场景上,自然取不到值。
  • 你把代码全部迁移到GameScene中就能正常运行,是因为你直接访问的是GameScene本身的属性,不需要依赖节点挂载后的scene属性获取场景实例。
修复方案

你可以调整代码执行顺序,或者修改参数传递逻辑来解决问题,两种常用方案如下:

方案1:调整节点挂载和初始化的顺序

先把节点添加到场景,再执行初始化配置:

private func addOuterMovingBlocks() {
    let shape = ExternalRingNode()
    // 先挂载到场景
    addChild(shape)
    // 再执行setup,此时scene属性已经有值
    shape.setup(number: 1)
}

方案2:把需要的参数直接传递给自定义节点,不需要依赖scene属性

这种方案耦合度更低,也更符合组件化设计思路:

// 修改ExternalRingNode的setup方法,直接接收需要的参数,比如这里你要用到的blocksCount
func setup(number: Int, blocksCount: Int) {
    path = draw(number, blocksCount: blocksCount).cgPath
}

func draw(_ number: Int, blocksCount: Int) -> UIBezierPath {
    // 不需要再访问scene属性,直接用传入的参数即可
    return UIBezierPath()
}

// 调用时直接从GameScene传值
private func addOuterMovingBlocks() {
    let shape = ExternalRingNode()
    shape.setup(number: 1, blocksCount: blocksCount)
    addChild(shape)
}

内容的提问来源于stack exchange,提问作者gmb55

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 21:27:01