我尝试使用SKSpriteNode
在SpriteKit中创建叠加层。但是,我希望触摸通过叠加层,因此我将isUserInteractionEnabled
设置为false。但是,当我这样做时,SKSpriteNode
仍然似乎吸收了所有的触摸,并且不允许底层节点做任何事情。
以下是我所谈论的一个例子:
class
TouchableSprite: SKShapeNode {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touch began")
}
}
class GameScene: SKScene {
override func sceneDidLoad() {
// Creat touchable
let touchable = TouchableSprite(circleOfRadius: 100)
touchable.zPosition = -1
touchable.fillColor = SKColor.red
touchable.isUserInteractionEnabled = true
addChild(touchable)
// Create overlay
let overlayNode = SKSpriteNode(imageNamed: "Fade")
overlayNode.zPosition = 1
overlayNode.isUserInteractionEnabled = false
addChild(overlayNode)
}
}
我尝试了将SKSpriteNode
子类化并手动将触摸事件委托给相应的节点,但这会导致许多奇怪的行为。
非常感谢任何帮助。谢谢!
答案 0 :(得分:6)
阅读您找到的实际来源:
/**
Controls whether or not the node receives touch events
*/
open var isUserInteractionEnabled: Bool
但这指的是内部节点触摸方法。
默认情况下,isUserInteractionEnabled
为 false ,默认情况下,对您的重叠SKSpriteNode
的触摸是对主(或父)类(对象)的简单触摸在这里,存在,但如果你没有实施任何行动,你只需触摸它)
要通过触摸浏览您的叠加层,您可以在GameScene
上实现下面的代码。请记住,不要将-1用作zPosition
,因为它意味着它位于您的场景之下。
PS :我已向您的精灵添加name
以将其召回touchesBegan
,但您可以为GameScene
创建全局变量:
override func sceneDidLoad() {
// Creat touchable
let touchable = TouchableSprite(circleOfRadius: 100)
touchable.zPosition = 0
touchable.fillColor = SKColor.red
touchable.isUserInteractionEnabled = true
touchable.name = "touchable"
addChild(touchable)
// Create overlay
let overlayNode = SKSpriteNode(imageNamed: "fade")
overlayNode.zPosition = 1
overlayNode.name = "overlayNode"
overlayNode.isUserInteractionEnabled = false
addChild(overlayNode)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("GameScene Touch began")
for t in touches {
let touchLocation = t.location(in: self)
if let overlay = self.childNode(withName: "//overlayNode") as? SKSpriteNode {
if overlay.contains(touchLocation) {
print("overlay touched")
if let touchable = self.childNode(withName: "//touchable") as? TouchableSprite {
if touchable.contains(touchLocation) {
touchable.touchesBegan(touches, with: event)
}
}
}
}
}
}
}
答案 1 :(得分:3)
你需要小心zPosition。有可能走到幕后,让事情变得复杂。
更糟糕的是触摸事件的顺序。我记得读过它是基于节点树而不是zPosition。禁用场景触摸,您应该看到结果。
这就是它现在所说的:
命中测试顺序是绘制顺序的反转在场景中,何时 SpriteKit处理触摸或鼠标事件,它遍历场景进行查找 想要接受事件的最近节点。如果该节点没有 想要事件,SpriteKit会检查下一个最近的节点,依此类推。该 处理命中测试的顺序基本上是相反的 绘图顺序。
对于在命中测试期间要考虑的节点,它 userInteractionEnabled属性必须设置为YES。默认值 除场景节点外的任何节点都为NO。想要接收的节点 事件需要从它实现适当的响应方法 父类(iOS上的UIResponder和OS X上的NSResponder)。这是一 您必须在其中实现特定于平台的代码的几个地方 SpriteKit。
但情况并非总是如此,因此您需要检查8,9和10之间的一致性