Swift游戏开发:如何禁用touchesBegan保留touchesMoved或反之?
解决SKNode滑动抖动:根据控制模式禁用对应触摸函数
嘿,这个问题我在开发2D触控游戏时也遇到过——滑动操作被touchesBegan误判成点击,导致节点来回跳,确实挺烦人的。下面是我亲测有效的几种实现方案,你可以根据自己的需求选:
方案一:用状态变量控制触摸函数的执行
这是最直接且易维护的方式,核心思路是用一个状态标记当前激活的控制模式,在每个触摸回调里先判断模式,不符合就直接返回。
步骤1:定义控制模式枚举
先创建一个枚举来明确支持的操作模式:
enum GameControlMode { case tap // 点击模式 case swipe // 滑动模式 } // 全局/场景内维护当前模式,默认可以设为点击 var currentControlMode: GameControlMode = .tap
步骤2:在触摸函数中加入模式判断
修改你的touchesBegan和touchesMoved函数,只有匹配当前模式时才执行逻辑:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { // 如果当前是滑动模式,直接跳过点击逻辑 guard currentControlMode == .tap else { return } // 原来的点击响应逻辑(比如节点定位、触发动作等) if let touch = touches.first { let location = touch.location(in: self) if yourNode.contains(location) { // 处理点击事件 } } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { // 如果当前是点击模式,直接跳过滑动逻辑 guard currentControlMode == .swipe else { return } // 原来的滑动响应逻辑(比如节点跟随触摸移动) if let touch = touches.first { let location = touch.location(in: self) yourNode.position = location } }
步骤3:切换控制模式
当用户在设置界面选择操作方式时,更新currentControlMode即可:
// 比如用户选择滑动控制 currentControlMode = .swipe
方案二:动态移除/添加触摸识别器(进阶)
如果你觉得在每个触摸函数里加判断不够优雅,可以用UITapGestureRecognizer和UIPanGestureRecognizer替代系统的触摸回调,通过启用/禁用手势识别器来切换模式:
// 初始化手势识别器 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:))) let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) // 添加到场景视图 view.addGestureRecognizer(tapGesture) view.addGestureRecognizer(panGesture) // 默认启用点击,禁用滑动 tapGesture.isEnabled = true panGesture.isEnabled = false // 切换模式的方法 func switchToControlMode(_ mode: GameControlMode) { tapGesture.isEnabled = (mode == .tap) panGesture.isEnabled = (mode == .swipe) } // 点击和滑动的处理函数 @objc func handleTap(_ gesture: UITapGestureRecognizer) { let location = gesture.location(in: view) // 转换为场景坐标 let sceneLocation = convertPoint(fromView: location) if yourNode.contains(sceneLocation) { // 处理点击 } } @objc func handlePan(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: view) let sceneTranslation = convertVector(translation, fromView: view) yourNode.position.x += sceneTranslation.x yourNode.position.y += sceneTranslation.y gesture.setTranslation(.zero, in: view) }
这种方式的好处是把触摸逻辑和模式控制完全分离,代码结构更清晰,适合复杂的触控场景。
为什么之前会抖动?
本质原因是滑动操作时,touchesBegan会先触发,执行了点击的节点移动逻辑,紧接着touchesMoved又触发滑动逻辑,两种逻辑交替作用就导致了节点抖动。通过禁用对应模式下的触摸函数,就能彻底避免这个问题。
内容的提问来源于stack exchange,提问作者James Taga
相关产品推荐
相关产品推荐

