1

Previously, I passed properties into my SKScene by creating initializers in my SKScene, then setting those initializers when i create my SKScene property in my SceneEditViewController. Did that make sense? I hope so.

However, instead of creating an SKScene manually, I am now using Scene Editor. My animation scene has a SKLabelNode and i want to pass text received from a different viewController into the SKScene's SKLabelNode. Below i provided my previous method in the "if" portion of my if-else. In the "else" portion, i'm attempting the new method but need help.

When trying to set a property from my SKScene, xcode states, "Value of type 'SKScene' has no member 'selectedTextSceneUse1'"

Included below:

  • SceneEditViewController
  • Extension enabling me to receive a text string from another viewController
  • GameScene.swift (swift file connected to my GameScene.sks)

I'm using swift 5.0, please let me know if you need additional information.

import UIKit
import Foundation
import SpriteKit
import GameplayKit

class SceneEditViewController: UIViewController, UITabBarControllerDelegate {

var selectedSceneTextFinal: String?

if selectedSceneInt == 0 {
            let animationScene3 = AnimationInventory18(size: CGSize(width:animationScreen.bounds.width, height:animationScreen.bounds.height), chosenChateracterSceneUse: chosenCharacterFinal, selectedTextSceneUse: selectedSceneTextFinal, chosenBackgroundSceneUse: chosenBackgroundFinal)
            
            animationScene3.scaleMode = .aspectFit
            animationScene3.backgroundColor = .black
            animationScene3.anchorPoint = CGPoint(x: 0.5, y: 0.52)
            animationScene3.position = CGPoint(x: 0, y: 0)
            let transition = SKTransition.fade(withDuration: 1.0)
            animationScreen.presentScene(animationScene3, transition: transition)
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 20){
                self.animationScreen.presentScene(nil)
                print("Scene Removed")
            }
        } else {
     
            if let scene = SKScene(fileNamed: "GameScene") as GameScene {
           
                scene.scaleMode = .aspectFit 
                
                scene.selectedTextSceneUse1 = selectedSceneTextFinal

                animationScreen.presentScene(scene)

                DispatchQueue.main.asyncAfter(deadline: .now() + 10){
                    self.animationScreen.presentScene(nil)
                    print("Scene Removed")
                }
            }
        }
    }

extension SceneEditViewController: textUpdateDelegate {
    func didUpdateText(textFromView: String){
        selectedSceneTextFinal = textFromView
    }
}


import SpriteKit
import GameplayKit

class GameScene: SKScene {
    
    var textNode: SKLabelNode?
    
   // Not receiving the value passed from selectedSceneTextFinal
   var selectedTextSceneUse1: String?
    

    // MARK: Camera Node
    let cameraNode = SKCameraNode()
    
    // Initializer 
     required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func check() {
        
        self.camera = cameraNode
        cameraNode.position = CGPoint(x: 0, y: -300)
        self.addChild(cameraNode)
        print(selectedTextSceneUse1)


        self.textNode?.text = selectedTextSceneUse1


    }
    
    override func sceneDidLoad() {

        self.lastUpdateTime = 0
        check()
    }

}


Ojay
  • 61
  • 12
  • @RonMyschuk you've been really helpful in the past, hoping you can provide help or clear what I'm missing. – Ojay Mar 02 '21 at 13:55

1 Answers1

3

You should cast your SKScene :

if let scene = SKScene(fileNamed: "GameScene") as? GameScene {

In these cases, as you get GameScene from file you need to implement the init?(coder..) :

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

Be sure to also setup the class type of the scene in the sks file. (custom class inspector)

If you want to setup sklabelnode text hen it change you could add observer on selectedSceneTextFinal :

class SceneEditViewController: UIViewController, UITabBarControllerDelegate {

   var gameScene : GameScene?
   var selectedSceneTextFinal: String? {
       didSet {
           // Update gameScene value when controller value is changed
           gameScene?.selectedTextSceneUse1 = selectedSceneTextFinal
       }
   }
...

        if let scene = SKScene(fileNamed: "GameScene") as GameScene {
            gameScene = scene
            scene.scaleMode = .aspectFit 
            scene.selectedTextSceneUse1 = selectedSceneTextFinal
...


class GameScene: SKScene {

    var textNode: SKLabelNode?

   // Update textNode on update of selectedTextSceneUse1
   var selectedTextSceneUse1: String? {
       didSet {
           // If nit done initialise textNode from sks file (label node must have a name)
           if textNode == nil {
               textNode = childNode(withName: "name of LabelNode in sks file") as? SKLabelNode
           }
           textNode?.text = selectedTextSceneUse1
       }
   }
Ptit Xav
  • 3,006
  • 2
  • 6
  • 15
  • you mean in "Show the File inspector" Under Identity and Type? – Ojay Feb 25 '21 at 20:39
  • No, in the custom class inspector – Ptit Xav Feb 26 '21 at 08:58
  • i had to remove the check because the property (selectedTextSceneUse1) I'm transferring the string to came back as nil. Is there something wrong with my initializer setup in the GameScene SKScene file? I'm now receiving a fatal error. Do i even need the initializer setup? – Ojay Feb 26 '21 at 13:44
  • I Forget that you havé to code the init : init?(coder...) : it must call super.init(coder...) – Ptit Xav Feb 27 '21 at 21:43
  • thanks a lot. i'm not sure i understand though. – Ojay Feb 27 '21 at 22:58
  • Added some explanations in the answer – Ptit Xav Mar 01 '21 at 10:16
  • For some reason ```selectedTextSceneUse1``` is nil when printing from the GameScene.swift file, however when i print ```scene.selectedTextScenUser1``` in SceneEditViewController, it prints the correct text. Not sure what's not working.. – Ojay Mar 01 '21 at 14:09
  • selectedTextSceneUse1 is declared as optional in GameScene class so its initial value is nil. In your code you initialise it just after scene creation with the view controller value. – Ptit Xav Mar 01 '21 at 15:28
  • oh, is there a way to initialize with the creation of scene? I thought i was okay, since i initialized before present scene – – Ojay Mar 01 '21 at 16:20
  • sorry to bother but we're so close! Apologies if I'm missing something simple. – Ojay Mar 02 '21 at 13:56
  • Added some lines to setup labelNode from gameSceneString which is setup from view controller. For the init , the problem is that init(fileNamed) is a convenience initialiser. – Ptit Xav Mar 02 '21 at 22:52
  • Thanks! I'm trying this out now, I've never used observers so this should be interesting. – Ojay Mar 03 '21 at 00:48
  • thanks for your help this cleaned it up. I appreciate you being patient with me. I'll have to read more about observers, this is really useful as an alternative way to pass things between a VC and custom classes. – Ojay Mar 03 '21 at 01:23
  • no issues with the code but curious why the code needs `scene.selectedTextSceneUse1 = selectedSceneTextFinal` when initializing gameScene file? – Ojay Mar 03 '21 at 14:05
  • It was just to set an initial value, but it may not be necessary depending on how/when selectedSceneTextFinal is updated. – Ptit Xav Mar 03 '21 at 14:38