能否为SKSpriteNode添加PanGestureRecognizer?报错解决方案咨询
解决SKSpriteNode添加UIPanGestureRecognizer的问题
你碰到的这个错误其实很好理解——SKSpriteNode是SpriteKit专属的节点类,它根本不是UIView的子类,而addGestureRecognizer是UIKit里UIView才有的方法,所以直接给SKSpriteNode调用这个方法肯定会报错。
下面给你两种实用的解决方案,推荐第一种,更贴合SpriteKit的使用逻辑:
方案一:将手势添加到SKView,判断触摸目标节点
这是最常用的方式,把手势绑定到SpriteKit的视图上,然后在手势回调里判断当前触摸的是不是你要拖拽的节点:
- 先把手势添加到SKView(而不是SKSpriteNode):
let myPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panMethod)) self.view?.addGestureRecognizer(myPanGestureRecognizer)
- 实现
panMethod方法,处理拖拽逻辑:
@objc func panMethod(_ sender: UIPanGestureRecognizer) { guard let skView = self.view else { return } // 把UIKit的触摸坐标转换成SpriteKit场景内的坐标 let touchLocationInView = sender.location(in: skView) let touchLocationInScene = skView.convert(touchLocationInView, to: self) // 找到当前触摸点对应的节点 let touchedNode = self.atPoint(touchLocationInScene) // 判断是不是我们要拖拽的那个node if touchedNode === node { switch sender.state { case .changed: // 更新节点位置 node.position = touchLocationInScene case .ended, .cancelled: // 拖拽结束后的逻辑(如果需要的话) break default: break } } }
如果你的场景里有多个可拖拽节点,可以给节点设置name属性来区分,比如node.name = "draggableBox",然后判断touchedNode.name == "draggableBox"即可。
方案二:用UIView包裹SKSpriteNode(仅特殊场景使用)
这种方法适合需要把SpriteKit节点和UIKit控件混合使用的场景,但会有坐标同步的问题,一般不推荐:
// 创建一个UIView作为容器 let containerView = UIView(frame: CGRect(x: 0, y: 0, width: node.size.width, height: node.size.height)) // 把容器视图的位置同步到节点的位置 if let skView = self.view { containerView.center = skView.convert(node.position, from: self) } self.view?.addSubview(containerView) // 给容器视图添加手势 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panViewHandler)) containerView.addGestureRecognizer(panGesture) // 手势回调里同步UIView和SKSpriteNode的位置 @objc func panViewHandler(_ sender: UIPanGestureRecognizer) { guard let panView = sender.view else { return } let translation = sender.translation(in: self.view) panView.center = CGPoint(x: panView.center.x + translation.x, y: panView.center.y + translation.y) sender.setTranslation(.zero, in: self.view) // 同步位置到SKSpriteNode if let skView = self.view { node.position = skView.convert(panView.center, to: self) } }
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

