One of the difficulties when working with software systems, including games, is complexity of state.
When working on a program, you should be able to think about what it will do, and what it will do is often dependent upon what state it's in. For example, if a ship were to fire a missile, the effect that might have would depend on where the ship was and which direction it was facing. More moving parts that can be in different positions make it more difficult to predict what the program will do at any time.
In an effort to combat this complexity, programmers will often try to hide stuff away. If each piece in a program is tucked into its own safe little corner, it can't affect the any of the other pieces. Therefore, when reasoning about the program and attempting to figure out what it will do, we can disregard all those little bits and pieces that are safely packed away. The state of the program is made simpler.
But sometimes this is inconvenient. Sometimes there are pieces that want to be accessed more often, by many parts of the program. Hiding these away into packages or modules isn't helpful. You can try to design around it, but sometimes it's unavoidable.
Bringing this back to Unity, Game Objects and their Behaviours are not very hidden away. By default, any object will be able to find and reach into the inner workings of any other. This makes sense for most game objects. If you have a script attached to a projectile, you would like for that script to be able to access some of the elements of the object it collides with.
Another feature of Behaviours in Unity is that they can be created and attached to many different objects, and each instance is unique and separate from the others. This makes sense for some Behaviours, but not others. Each ship should have it's own model, but it wouldn't make sense to create multiple instances of the camera controls.
All this leads us to two design concerns:
-Sometimes you only ever want there to be one of something
and
-Sometimes you want something to be globally accessible
The solution to these problems, is the Singleton pattern. In short, it consists of a class that cannot be instantiated, but provides access to one, and only one, instance of itself.
For regular C# objects, this means that the constructor methods are hidden away, and are only called to create the one reference copy.
For Unity MonoBehaviours, this means that one instance of the Behaviour is created and attached to an object in the scene, and any other attempts to create that MonoBehaviour will instead point to the original copy. This idea is described more at Unity Patterns.
Battle Engine Update
Nothing too flashy to report here. You may have difficulty playing spot-the-difference from the last post.-Ships now have headings, they can face in any of 6 directions (though they're all facing NW in this image).
-The engine now correctly identifies whether not a ship is present within a hex when that hex is clicked in (which was a little spotty before).
-And last of all, the View now subscribes to the Model and receives Events, which it uses to update its representation of the game's state. What does that mean? Well, it doesn't change anything from the outward appearance, but it makes the internal code more robust and expandable. I'll be talking more about it in the next article.
No comments:
Post a Comment