Search code examples
swiftxcodesprite-kitskactiongameplay-kit

how to access entity from code - gameplay kit


I have a node I added in the scene. Also in the scene I give it a component to bounce. The component looks like this:

class BounceComponent: GKComponent, ComponentSetupProt {

var bounce: SKAction?
var node: SKSpriteNode?

@GKInspectable var diff: CGFloat = 0.2
@GKInspectable var startScale: CGFloat = 1
@GKInspectable var duration: TimeInterval = 0.5

override init() {
    super.init()
    comps.append(self)
}

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

func setup() {
    print("setup")
    node = entity?.component(ofType: GKSKNodeComponent.self)!.node as? SKSpriteNode
    setupBounce()
}

func setupBounce() {
    ...
}

func performBounce() {
    print("performing")
    node?.run(bounce!)
}
}//

In the didMove function on my scene file, it calls the components setup(). This works fine. I'm trying to call the function performBounce() when I click on the button...

    if (play?.contains(pos))! {
        print("test")
        if let _ = play?.entity {
            print("we have an entity")
        }
        play?.entity?.component(ofType: BounceComponent.self)?.performBounce()
    }

When I click, the only thing it prints is "test" and the entity is nil. I was under the assumption that when you add a node to the editor, it also sets up the entity for that node, so I'm not sure why it is nil. Curious if anyone could shed some light on this?

Thanks for any help!


Solution

  • The entity on the SKSpriteNode is a weak reference, you need to make sure you retain your entities from your gameplaykit object

    class GameViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Load 'GameScene.sks' as a GKScene. This provides gameplay related content
            // including entities and graphs.
            if let scene = GKScene(fileNamed: "Main") {
    
                // Get the SKScene from the loaded GKScene
                if let sceneNode = scene.rootNode as? Main {
    
                    sceneNode.entities = scene.entities // add this
    
                    // Set the scale mode to scale to fit the window
                    sceneNode.scaleMode = .aspectFill
    
                    // Present the scene
                    if let view = self.view as! SKView? {
                        view.presentScene(sceneNode)
                        view.showsDrawCount = true
                        view.ignoresSiblingOrder = true
                        view.showsFPS = true
                        view.showsNodeCount = true
                    }
                }
            }
        }
    
    
    
    class Main: Base {
        var entities = [GKEntity]() // add this