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

游戏界面暂停按钮无法选中的原因分析与解决方法咨询

问题分析与解决方案

咱们来拆解你遇到的触摸检测问题,核心原因出在坐标空间不匹配和触摸检测的坐标系选择上,下面一步步说清楚:

1. 核心问题:坐标系错位

你的暂停按钮是topBar的子节点,它的位置是相对于topBar的本地坐标系的,但你在判断pauseButton.contains(touch.location(in: self))时,用的是场景(self)的坐标系,这两个坐标系的位置不匹配,自然检测不到触摸。

另外,nodes(at: touch.location(in: self))只返回背景和道路,大概率是因为topBar或者pauseButton的触摸区域没有正确落在你点击的位置——毕竟你是通过SKAction移动topBar的,要确认移动后的位置是否真的让按钮处于可点击区域。

2. 具体修复步骤

步骤1:修正触摸检测的坐标系

把判断按钮是否被触摸的代码,改成使用topBar的本地坐标系:

if pauseButton.contains(touch.location(in: topBar)) {
    print("paused")
}

这样就能正确匹配按钮在父节点topBar里的位置了。

步骤2:确保节点允许交互(可选但推荐)

默认情况下,SKSpriteNode的isUserInteractionEnabled是false,虽然场景的touchesBegan可以通过nodes(at:)检测,但显式开启可以避免潜在问题:

// 初始化topBar时添加
topBar.isUserInteractionEnabled = true
// 初始化pauseButton时添加
pauseButton.isUserInteractionEnabled = true

步骤3:验证topBar的最终位置是否正确

你用SKAction.moveTo(y: (screenHeight/2) - (topBar.size.height/2), duration: 0.5)移动顶部栏,这个位置是否正确?可以在移动完成后打印topBar.position确认:

topBar.run(SKAction.moveTo(y: (screenHeight/2) - (topBar.size.height/2), duration: 0.5)) {
    print("topBar final position: \(self.topBar.position)")
}

如果位置不对,调整y值的计算——比如如果你的场景是使用SKSceneScaleMode.aspectFill或其他缩放模式,可能需要重新计算屏幕边界。

步骤4:优化nodes(at:)的检测逻辑

如果你还是想用nodes(at:)获取触摸节点,可以先确保获取的是最上层的节点(zPosition最高的),因为nodes(at:)会返回所有包含触摸点的节点,按zPosition从低到高排序,所以你应该取最后一个元素:

let touchLocation = touch.location(in: self)
let nodesAtLocation = nodes(at: touchLocation)
// 遍历从后往前,优先检测zPosition高的节点
for node in nodesAtLocation.reversed() {
    print(node.name)
    if node.name == pauseButtonName {
        print("paused")
        break // 找到目标节点后跳出循环
    }
}

这样就能优先检测到zPosition为4的顶部栏和按钮,而不是被背景/道路抢占。

3. 完整测试代码示例

修改后的touchesBegan函数可以写成这样:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    
    // 方法1:直接检测按钮(推荐)
    if pauseButton.contains(touch.location(in: topBar)) {
        print("paused")
        return
    }
    
    // 方法2:遍历节点
    let touchLocation = touch.location(in: self)
    for node in nodes(at: touchLocation).reversed() {
        guard let nodeName = node.name else { continue }
        print(nodeName)
        if nodeName == pauseButtonName {
            print("paused")
            break
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:29:05