Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GKEntity/Component update cycle best practices

The subject

My question is about the division of the update cycle when combining Apple's frameworks in order to respect the typical patterns and good practices on the subject, since most of the documentation and example code has not been adapted to Swift yet (or at least I can't find it anywhere).

There are so many ways to manage the update cycles in GameplayKit that I'm not too sure what is a good way of combining everything.

The elements

First and foremost: every class (GKComponent and GKEntity (sub)classes) in the Entity/Component has an update() method that you can override to perform per-frame updates. That has to come from the update cycle of the current GKScene/SKScene.

Then you have the GKComponentSystem that you can use to fire up the update() methods of every component from a given type that has been added to it. I see the point, it's very handy.

But I also want to use the state machine system and it also has an update cycle of it's own... Combining all that got me confused.

My situation

In the case where I have a subclass of GKEntity with an instance of a GKStateMachine created on initialization. The state machine has a few states (for the moment: 'Spawn', 'Normal', 'Stunned' and 'Death'.

State cycle

Right now, I'm creating a big "cookie cutter" with my GKEntity subclasses and create all the components it's gonna use during the initialization. But it's becoming very impractical. For instance, I have a MovementComponent, which is a subclass of GKAgent2D. I created a singleton that manages entity creation, so after the instance is created, if loops through all the entity's components and add them to the related GKComponentSystems. The singleton has an update() method of it's own that updates passes the call to the GKComponentSystems. Some of the components I use do not need per-frame update, so no GKComponentSystem has been created for them and I update them manually as required.

If I come back to my entity, since I create everything at once and use GKComponentSystems to update the components, my component's update method is loaded with guard and if-let statements because I need to access the entity's state machine, check if it's a state where the entity can move (Normal state) and do its thing or escape the function. This is not efficient in my view: the move component doesn't need to get updated when it's spawning, stunned, or dying.

On top of that it makes my use of GKStateMachine completely overkill since my update methods are empty: the components get updated by the GKComponentSystem anyway.

My ideas

  1. Drop the GKComponentSystems completely and simply loop through all my entities (maybe sort them in different collections at some point if need be) and call their update() methods. Dispatch the updates to the state machine which in turn will update the components involved in that state.

  2. Keep the GKComponentSystems and use the state machine to juggle with the components, for example by adding and removing the MovementComponent from the component systems when entering and exiting the Normal state.

Option 1 is straightforward but could cause problems on the long run when my structure gets more complex becasue some components could need to be updated before others. Having each entity update its own components would scatter the update process.

Option 2 can get confusing too in a way, but my biggest concern is about the creation/removal of the components. Do I only take them out of the GKComponentSystems or do I take them out of the entity completely? What is the most efficient way of doing it?

The actual question

which one of my options would be the best? is there any better way of doing it.

like image 567
BadgerBadger Avatar asked Jan 15 '17 19:01

BadgerBadger


1 Answers

If you are using GKComponentSystem to perform updates, then I would go with just that. I think a component should update only once per frame.

It's not clear from your question what you need to do with StateMachines, but there is no reason to not have them involved either directly in your GKEntity or contained within a GKComponent like the DemoBots IntelligenceComponent.

like image 177
Mark Brownsword Avatar answered Sep 22 '22 08:09

Mark Brownsword