检测对以编程方式构建的节点的接触?无法正确访问节点名称?

问题描述

所以我通过构建像这样的 buildCharacter 方法解决了关于减少重复代码的其他问题之一 -

 func buildCharacter(name:String,height: CGFloat,width: CGFloat,position: CGPoint,zPosition: CGFloat) {
    let animatedAtlas = SKTextureAtlas(named: name)
    var animationFrames: [SKTexture] = []
    
    let numImages = animatedAtlas.textureNames.count
    for i in 1...numImages {
        let textureName = "\(name)\(i)"
        
        animationFrames.append(animatedAtlas.textureNamed(textureName))
    }
    
    animatedCharacter = animationFrames
    let firstFrameTexture = animatedCharacter[0]
    builtCharacter = SKSpriteNode(texture: firstFrameTexture)
    builtCharacter.size.height = height
    builtCharacter.size.width = width
    builtCharacter.position = position
    builtCharacter.zPosition = zPosition
    builtCharacter.name = name
    
    isUserInteractionEnabled = true
    addChild(builtCharacter)
    
   }

然后我像这样在每个场景的基础上调用它们 -

buildCharacter(name: "Bear",height: 370,width: 370,position: CGPoint(x: 295,y: 25),zPosition: 10)

buildCharacter(name: "Cat",height: 240,width: 240,position: CGPoint(x: 134,y: -38),zPosition: 12)

这在构建它们并将它们添加到场景中非常有效,但是我正在努力检测触摸,然后为它们设置动画。我以前的 touchesBegan 看起来像这样 -

func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {

    super.touchesBegan(touches,with: event)

    if let touch = touches.first {
           let location = touch.location(in: self)

           var closest:CGFloat?
            let nodes = nodes(at:location)
            for node in nodes as [SKNode] {
               if let sprite = node as? SKSpriteNode {
                   // Calculate the distance from the node to the touch
                   let dx = location.x - node.position.x
                   let dy = location.y - node.position.y
                   let distance = dx*dx + dy*dy
                   // Find the closest
                   if closest == nil || distance < closest! {
                       closest = distance
                       selectednode = sprite

                   }
               }
           }
       }

switch selectednode {
        case bear:
            
            if builtCharacter.hasActions() {
                SoundEngine.shared.stopBackgroundMusic(fadeOut: false)
                stopAllAnimation()
            } else {
                SoundEngine.shared.playBackgroundMusic("blueRail.aif",loop: false)
                startAllAnimation()
            }
        case cat:
            
            if cat.hasActions() {
                SoundEngine.shared.stopBackgroundMusic(fadeOut: false)
                stopAllAnimation()
            } else {
                SoundEngine.shared.playBackgroundMusic("cluckOldHen.aif",loop: false)
                animateCat()
                dispatchQueue.main.asyncAfter(deadline: .Now() + 2.0) {
                    self.startAllAnimation()
                   }

            }

所以基本上我正在努力访问节点名称?我尝试了 builtCharacter.name 并无法弄清楚......我想我可以在 touchesBegan 中做一些不同的事情,或者在 buildCharacter 方法添加一些东西?

我知道我可以很容易地在故事板中做到这一点,这是我的备用计划 - 只是想通过这种方法学习更多。提前致谢!

解决方法

好吧,在@Mark Szymczyk 的帮助下解决了这个问题。由于 SKNode 的 name 属性是可选的,我必须在 if let 语句中运行 switch 并打开非可选名称

 if let nodeName = selectedNode.name {
            switch nodeName {
                    case "Bear" :
                        print("Bear touched")
                    case "Cat":
                        print("Cat touched")
                    default:
                        print("No node touched")

现在我可以访问节点名称并检测触摸。