3

I'm working on a small project using SpriteKit and GameplayKit. It's my first time using an entity/component system and I'm loving it. But now, I'm at a point where I need to keep track of my entities states (Spawning, Normal, Removing) so they don't interact during their spawning phase (which may or may not include actions to animate the thing) and their removing phase.

So far, I've created a EntityStateComponent which instanciate a GKStateMachine with the different states and since there is no need for per-frame updates it's not that complicated. The thing is that this state is more entity related than component related and I'm wondering if it would make sense to subclass from GKEntity and add the state machine in there instead of in a component.

Your thoughts?

PS: I'm already sub-classing from GKEntity just to have a convenience init() that creates all the components

BadgerBadger
  • 696
  • 3
  • 12

1 Answers1

3

You are right, state is entity related, not component related. Put the state machine into the entity directly, or create an entity base class that all your entities inherit from.

class VisualEntityBase : GKEntity, VisualEntity {
    var node: SKSpriteNode!
    var stateMachine: GKStateMachine!


    // MARK: Initialization

    init(imageNamed: String, atStartPosition: CGPoint) {
        super.init()

        // Initialise Texture
        let texture = SKTexture(imageNamed: imageNamed)

        // Initialise Node
        self.node = SKSpriteNode(texture: texture, size: texture.size())
        self.node.position = atStartPosition

        // Initialise StateMachine
        self.stateMachine = GKStateMachine(states: [
            VisualEntityIdle(),
            VisualEntityPendingMove(),
            VisualEntityMoving()
        ])

        self.stateMachine.enter(VisualEntityIdle.self)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Mark Brownsword
  • 2,287
  • 2
  • 14
  • 23
  • Thanks a lot for that! I was refraining from adding anything to my GKEntity subclasses because that's the "textbook" way of doing it, but having to use optional chaining and forced unwrapping all the time felt wrong at some point. And making a per-frame update inside a component for something that is entity related is impossible anyway. – BadgerBadger Jan 06 '17 at 06:06
  • 1
    This [article](https://www.gamedev.net/resources/_/technical/game-programming/implementing-component-entity-systems-r3382) helped me understand `ECS`, worth a read, if you haven't seen it. – Mark Brownsword Jan 06 '17 at 08:05
  • 1
    Also, the [Demobots Example](https://developer.apple.com/library/content/samplecode/DemoBots/Introduction/Intro.html#//apple_ref/doc/uid/TP40015179) uses an `IntelligenceComponent` that contains `GKStateMachine`. – Mark Brownsword Jan 09 '17 at 18:58
  • @MarkBrownsword, Sorry I feel like your above example (Demobots) contradicts with your answer! Could you please more specific on the example, why they put state machine in the component? – arunjos007 Dec 10 '18 at 12:14