|
| 1 | +# OctopusKit Tips & Troubleshooting |
| 2 | + |
| 3 | +1. [Common Mistakes](#common-mistakes) |
| 4 | +2. [Best Practices](#best-practices) |
| 5 | +3. [Tips & Tricks](#tips-&-tricks) |
| 6 | +4. [Pitfalls & Gotchas](#pitfalls-&-gotchas) |
| 7 | +5. [Conditional Compilation Flags & Debugging Aids](#conditional-compilation-flags-&-debugging-aids) |
| 8 | + |
| 9 | +## Common Mistakes |
| 10 | + |
| 11 | +#### Components not having any effect? |
| 12 | +- If the component has an `update(deltaTime:)` method, make sure it's registered with a Component System, or is manually updated during the scene's `update(_:)` method, and *is only updated* ***once!*** [TODO: make this automatic] |
| 13 | + |
| 14 | +- Does the entity have all the components that the non-functioning component depends on? A component's dependencies must be added to the entity before the component that depends on them. [TODO: make this automatic] |
| 15 | + |
| 16 | +- Check the log. |
| 17 | + |
| 18 | +#### Components having *too* much effect? |
| 19 | +- Make sure that a component is updated (if applicable) only once per frame. |
| 20 | + |
| 21 | +- Also make sure that a component *system* is added to a scene only once! |
| 22 | + |
| 23 | +#### Gesture recognizer components not working? |
| 24 | +- Check their properties for the minimum and maximum number of touches. |
| 25 | + |
| 26 | +#### Scene, subscene or node not receiving input events? |
| 27 | +- Check its `isUserInteractionEnabled` property. |
| 28 | + |
| 29 | +## Best Practices |
| 30 | + |
| 31 | +- Remember to search the entire source code for `BUG:`, `APPLEBUG:`, `FIXME:` etc. comments for any outstanding bugs and their temporary workarounds, if any. |
| 32 | + |
| 33 | +- In most cases, try to access the object hierarchy from the "bottom up" instead of "top down." |
| 34 | + |
| 35 | + > TODO: Example |
| 36 | + |
| 37 | +## Tips & Tricks |
| 38 | + |
| 39 | +- You can have multiple "games" within a single project, by using multiple `OctopusGameController`s (each with its own set of `OctopusGameState`s and associated scenes, etc.) and programmatically choosing between them in `OctopusAppDelegate.configureOctopusEngine()`. |
| 40 | + |
| 41 | +- TODO: Tip for sharing "global" data via `RelayComponent`s. |
| 42 | + |
| 43 | +## Pitfalls & Gotchas |
| 44 | + |
| 45 | +- Many methods MUST be overridden in a subclass and/or chained to the superclass implementation, by calling `super.method()`. Some methods should call `super` at different points (i.e. beginning or end) in the subclass' implementation. Unfortunately, there is no language-level support for enforcing that, so your best bet is to read the source and comments of the method you're overriding. |
| 46 | + > 💡 When in doubt, always call `super`, and call it at the top of your overriding method. [TODO: make this chaining automatic/enforced when/if Swift supports it] |
| 47 | + |
| 48 | +- Components should try to perform their logic only during the `didAdd(...)`, `willRemove(...)`, and `update(deltaTime:)` methods. If a component's behavior must be modified outside of those methods, use flags that are then acted upon in the component's update method. |
| 49 | +This ensures that a component does not affect anything outside of a frame update and can be reliably paused/unpaused. |
| 50 | + > Note that this does not mean that a component should not _define_ any other methods at all. |
| 51 | + > TODO: Example |
| 52 | + |
| 53 | + - Components that respond to asynchronous events, such as a component that moves a node based on input from a gesture recognizer, like `PanControlledRepositioningComponent`, or networking components, MUST perform their function inside their `update(deltaTime:)` method, and just use the event-handling action method to mark a flag to denote that an event was received. |
| 54 | +This prevents the component from being active outside the frame-update cycle, or when it's [temporarily] removed from the entity or the scene's systems. |
| 55 | + |
| 56 | + - A SpriteKit scene processes touch and other input events **outside** of its `update(_:)` method; when those event handlers update input-processing components, those components will (should) only be able to act on the input data during the scene's `update(_:)` method. |
| 57 | + |
| 58 | +- OctopusKit components may sometimes cause some "friction" against the SpriteKit API. |
| 59 | + e.g.: when adding a `SpriteKitComponent` and a `PhysicsComponent` to an entity; the SpriteKit node may have its own `physicsBody` and the `PhysicsComponent` may have a different `physicsBody`. |
| 60 | + - As a general rule, adding a component to an entity assumes that the component adds its encapsulated functionality to that entity, replacing any identical functionality that already exists. |
| 61 | + |
| 62 | + > e.g.: If you add a "blank" component, e.g. a `PhysicsComponent` with a `nil` `physicsBody`, then the component attempts to "adopt" any existing properties of the underlying SpriteKit object. |
| 63 | + In this example, the blank `PhysicsComponent` will set its property to the `physicsBody`, if any, of the `SpriteKitComponent` node. After that, other components should access the node's physics properties through the `PhysicsComponent` instead of the node's `physicsBody` property. |
| 64 | + |
| 65 | +- Entities and components may not always be the answer to everything. *Sometimes* good old classes and structs may be the better solution. (^ - ^") |
| 66 | + |
| 67 | +- An entity can/should only have one component of a specific type (not counting generic variants.) |
| 68 | +If an entity needs multiple components of the same type but with different parameters, consider using a "master" component that holds a collection of regular classes/struct. |
| 69 | + > e.g.: a *ShipEntity* with a *WeaponsSystemComponent* that holds an array of *Gun* classes/structs, to represent multiple guns where each gun is mounted on a different side of the ship. |
| 70 | + |
| 71 | +## Conditional Compilation Flags & Debugging Aids |
| 72 | + |
| 73 | +> TODO: Instructions on where to enter these in Xcode |
| 74 | +
|
| 75 | +* `LOGINPUT` - Logs all input events and related information. |
| 76 | + |
| 77 | +---- |
| 78 | + |
| 79 | +OctopusKit © 2018 InvadingOctopus.com, github.com/invadingoctopus/octopuskit |
| 80 | +[Apache License 2.0][license] |
| 81 | + |
| 82 | +[license]: https://www.apache.org/licenses/LICENSE-2.0.html |
0 commit comments